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-11-12 08:59:49 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-06 12:55
      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           0 : rsclustercon_t*    cluster_new(const cluster_t* cluster) {
      39           0 :     rsclustercon_t* rsclustercon = NULL;
      40             : 
      41           0 :     if (NULL==(rsclustercon=malloc(sizeof(struct rsclustercon_s)))) {
      42           0 :         perror("cluster_new");
      43           0 :         return NULL;
      44             :     }
      45           0 :     if (NULL==(rsclustercon->host=strdup(cluster->host))) {
      46           0 :         perror("cluster_new host");
      47           0 :         free(rsclustercon);
      48           0 :         return NULL;
      49             :     }
      50           0 :     if (NULL==(rsclustercon->user=strdup(cluster->user))) {
      51           0 :         perror("cluster_new user");
      52           0 :         free(rsclustercon->host);
      53           0 :         free(rsclustercon);
      54           0 :         return NULL;
      55             :     }
      56           0 :     if (NULL==(rsclustercon->pass=strdup(cluster->pass))) {
      57           0 :         perror("cluster_new pass");
      58           0 :         free(rsclustercon->user);
      59           0 :         free(rsclustercon->host);
      60           0 :         free(rsclustercon);
      61           0 :         return NULL;
      62             :     }
      63           0 :     if (NULL==(rsclustercon->cacert=strdup(cluster->cacert))) {
      64           0 :         perror("cluster_new cacert");
      65           0 :         free(rsclustercon->pass);
      66           0 :         free(rsclustercon->user);
      67           0 :         free(rsclustercon->host);
      68           0 :         free(rsclustercon);
      69           0 :         return NULL;
      70             :     }
      71           0 :     rsclustercon->insecure = strcmp(cluster->insecure,"false");
      72           0 :     return rsclustercon;
      73             : }
      74             : 
      75           0 : int   cluster_open(rsclustercon_t* rsclustercon) {
      76             :     struct sockaddr_in server_addr;
      77             : 
      78             :     /* Socket creation */
      79           0 :     rsclustercon->sock = socket(AF_INET, SOCK_STREAM, 0);
      80           0 :     if (rsclustercon->sock < 0) {
      81           0 :         perror("Socket creation error");
      82           0 :         return 1;
      83             :     }
      84             : 
      85           0 :     server_addr.sin_family = AF_INET;
      86           0 :     server_addr.sin_port = htons(9443);
      87           0 :     if (inet_pton(AF_INET, rsclustercon->host, &server_addr.sin_addr) <= 0) {
      88           0 :         perror("Invalid address");
      89           0 :         return 2;
      90             :     }
      91             : 
      92             :     /* Server connection */
      93           0 :     if (connect(rsclustercon->sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
      94           0 :         perror("Connection failed");
      95           0 :         return 3;
      96             :     }
      97             : 
      98             :     /* OpenSSL initialization */
      99           0 :     SSL_library_init();
     100             :     /* OpenSSL_add_all_algorithms(); */
     101           0 :     OpenSSL_add_ssl_algorithms();
     102           0 :     SSL_load_error_strings();
     103             : 
     104             :     /* Initialize OpenSSL context */
     105           0 :     rsclustercon->ctx = SSL_CTX_new(SSLv23_client_method());
     106           0 :     if (!rsclustercon->ctx) {
     107           0 :         ERR_print_errors_fp(stderr);
     108           0 :         return 4;
     109             :     }
     110             : 
     111             :     /* Load server certificate or certificate from a certification authority (CA) */
     112           0 :     if (strcmp("",rsclustercon->cacert)&&rsclustercon->insecure==0)
     113           0 :         if (SSL_CTX_load_verify_locations(rsclustercon->ctx, rsclustercon->cacert, NULL) != 1) {
     114           0 :             ERR_print_errors_fp(stderr);
     115           0 :             return 5;
     116             :         }
     117             : 
     118           0 :     if (rsclustercon->insecure)
     119             :         /* Disable certificat check */
     120           0 :         SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_NONE, NULL);
     121             :     else
     122             :         /* Enable certificat check */
     123           0 :         SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_PEER, NULL);
     124             : 
     125             : 
     126             :     /* Link SSL configuration to the socket */
     127           0 :     rsclustercon->ssl = SSL_new(rsclustercon->ctx);
     128           0 :     SSL_set_fd(rsclustercon->ssl, rsclustercon->sock);
     129             : 
     130             :     /* Initiate SSL connection */
     131           0 :     if (SSL_connect(rsclustercon->ssl) <= 0) {
     132           0 :         ERR_print_errors_fp(stderr);
     133           0 :         return 6;
     134             :     }
     135             : 
     136           0 :     return 0;
     137             : }
     138             : 
     139           0 : cJSON* cluster_queryget(const rsclustercon_t* rsclustercon, const char* endpoint) {
     140             :     char buf[1024];
     141             : 
     142             :     /* Prepare basic authentication */
     143             :     char* auth_encoded;
     144             :     {
     145             :         char* auth_clear;
     146           0 :         if (NULL==(auth_clear = (char*)malloc(strlen(rsclustercon->user)+1+strlen(rsclustercon->pass)+1))) {
     147           0 :             perror("cluster_queryget malloc(auth)");
     148           0 :             return NULL;
     149             :         };
     150           0 :         strcpy(auth_clear,rsclustercon->user);
     151           0 :         strcat(auth_clear,":");
     152           0 :         strcat(auth_clear,rsclustercon->pass);
     153           0 :         auth_encoded=base64_encode(auth_clear);
     154           0 :         free(auth_clear);
     155             :     }
     156             : 
     157             :     /* Prepare query */
     158             :     char http_request[512];
     159           0 :     snprintf(http_request, sizeof(http_request),
     160             :              "GET %s HTTP/1.1\r\n"
     161             :              "Host: %s\r\n"
     162             :              "Content-Type: application/json\r\n"
     163             :              "Authorization: Basic %s\r\n"
     164             :              "Connection: close\r\n\r\n",
     165           0 :              endpoint,rsclustercon->host,auth_encoded
     166             :             );
     167           0 :     free(auth_encoded);
     168             : 
     169             :     /* Send query */
     170           0 :     SSL_write(rsclustercon->ssl, http_request, strlen(http_request));
     171             : 
     172             :     /* Read reply */
     173           0 :     int bytes=0;
     174           0 :     char* reply=NULL;
     175           0 :     if (NULL==(reply=strdup(""))) {
     176           0 :         perror("cluster_queryget strdup");
     177           0 :         return NULL;
     178             :     };
     179           0 :     while ((bytes=SSL_read(rsclustercon->ssl, buf, 1024 - 1)) > 0) {
     180           0 :         buf[bytes] = 0;
     181             :         char* newreply;
     182           0 :         if ((newreply=(char*)realloc(reply,strlen(reply)+bytes+1))==NULL) {
     183           0 :             perror("Unable to allocate reply buffer");
     184           0 :             free(reply);
     185           0 :             return NULL;
     186             :         } else
     187           0 :             reply = newreply;
     188           0 :         strcat(reply, buf);
     189             :     }
     190             : 
     191             :     /* Remove HTTP headers */
     192             :     char* http_body;
     193             :     char* retval_txt;
     194           0 :     if (NULL==(http_body = strstr(reply,"\r\n\r\n")))
     195           0 :         retval_txt= NULL;
     196             :     else
     197           0 :         retval_txt=strdup(http_body);
     198           0 :     free(reply);
     199             : 
     200           0 :     cJSON* retval_json = cJSON_Parse(retval_txt);
     201           0 :     free(retval_txt);
     202             : 
     203           0 :     return retval_json;
     204             : }
     205             : 
     206           0 : void  cluster_close(rsclustercon_t* rsclustercon) {
     207           0 :     SSL_shutdown(rsclustercon->ssl);
     208           0 :     SSL_free(rsclustercon->ssl);
     209           0 :     close(rsclustercon->sock);
     210           0 :     SSL_CTX_free(rsclustercon->ctx);
     211           0 :     EVP_cleanup();
     212           0 : }
     213             : 
     214           0 : void  cluster_del(rsclustercon_t* rsclustercon) {
     215           0 :     free(rsclustercon->cacert);
     216           0 :     free(rsclustercon->pass);
     217           0 :     free(rsclustercon->user);
     218           0 :     free(rsclustercon->host);
     219           0 :     free(rsclustercon);
     220           0 : }
     221             : 
     222             : /* vim: set tw=80: */

Generated by: LCOV version 1.16