rsstats 0.0.1
Redis Enterprise Statistic collector
clustercon.c
Go to the documentation of this file.
1
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
38typedef 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;
48
50 rsclustercon_t* rsclustercon = NULL;
51
52 if (NULL==(rsclustercon=malloc(sizeof(struct rsclustercon_s)))) {
53 perror("cluster_new");
54 return NULL;
55 }
56 if (NULL==(rsclustercon->host=strdup(cluster->host))) {
57 perror("cluster_new host");
58 free(rsclustercon);
59 return NULL;
60 }
61 if (NULL==(rsclustercon->user=strdup(cluster->user))) {
62 perror("cluster_new user");
63 free(rsclustercon->host);
64 free(rsclustercon);
65 return NULL;
66 }
67 if (NULL==(rsclustercon->pass=strdup(cluster->pass))) {
68 perror("cluster_new pass");
69 free(rsclustercon->user);
70 free(rsclustercon->host);
71 free(rsclustercon);
72 return NULL;
73 }
74 if (NULL==(rsclustercon->cacert=strdup(cluster->cacert))) {
75 perror("cluster_new cacert");
76 free(rsclustercon->pass);
77 free(rsclustercon->user);
78 free(rsclustercon->host);
79 free(rsclustercon);
80 return NULL;
81 }
82 rsclustercon->insecure = strcmp(cluster->insecure,"false");
83 return rsclustercon;
84}
85
86int cluster_open(rsclustercon_t* rsclustercon) {
87 struct sockaddr_in server_addr;
88
89 /* Socket creation */
90 rsclustercon->sock = socket(AF_INET, SOCK_STREAM, 0);
91 if (rsclustercon->sock < 0) {
92 perror("Socket creation error");
93 return 1;
94 }
95
96 server_addr.sin_family = AF_INET;
97 server_addr.sin_port = htons(9443);
98 if (inet_pton(AF_INET, rsclustercon->host, &server_addr.sin_addr) <= 0) {
99 perror("Invalid address");
100 return 2;
101 }
102
103 /* Server connection */
104 if (connect(rsclustercon->sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
105 perror("Connection failed");
106 return 3;
107 }
108
109 /* OpenSSL initialization */
110 SSL_library_init();
111 /* OpenSSL_add_all_algorithms(); */
112 OpenSSL_add_ssl_algorithms();
113 SSL_load_error_strings();
114
115 /* Initialize OpenSSL context */
116 rsclustercon->ctx = SSL_CTX_new(SSLv23_client_method());
117 if (!rsclustercon->ctx) {
118 ERR_print_errors_fp(stderr);
119 return 4;
120 }
121
122 /* Load server certificate or certificate from a certification authority (CA) */
123 if (strcmp("",rsclustercon->cacert)&&rsclustercon->insecure==0)
124 if (SSL_CTX_load_verify_locations(rsclustercon->ctx, rsclustercon->cacert, NULL) != 1) {
125 ERR_print_errors_fp(stderr);
126 return 5;
127 }
128
129 if (rsclustercon->insecure)
130 /* Disable certificat check */
131 SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_NONE, NULL);
132 else
133 /* Enable certificat check */
134 SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_PEER, NULL);
135
136
137 /* Link SSL configuration to the socket */
138 rsclustercon->ssl = SSL_new(rsclustercon->ctx);
139 SSL_set_fd(rsclustercon->ssl, rsclustercon->sock);
140
141 /* Initiate SSL connection */
142 if (SSL_connect(rsclustercon->ssl) <= 0) {
143 ERR_print_errors_fp(stderr);
144 return 6;
145 }
146
147 return 0;
148}
149
150cJSON* 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 if (NULL==(auth_clear = (char*)malloc(strlen(rsclustercon->user)+1+strlen(rsclustercon->pass)+1))) {
158 perror("cluster_queryget malloc(auth)");
159 return NULL;
160 };
161 strcpy(auth_clear,rsclustercon->user);
162 strcat(auth_clear,":");
163 strcat(auth_clear,rsclustercon->pass);
164 auth_encoded=base64_encode(auth_clear);
165 free(auth_clear);
166 }
167
168 /* Prepare query */
169 char http_request[512];
170 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 endpoint,rsclustercon->host,auth_encoded
177 );
178 free(auth_encoded);
179
180 /* Send query */
181 SSL_write(rsclustercon->ssl, http_request, strlen(http_request));
182
183 /* Read reply */
184 int bytes=0;
185 char* reply=NULL;
186 if (NULL==(reply=strdup(""))) {
187 perror("cluster_queryget strdup");
188 return NULL;
189 };
190 while ((bytes=SSL_read(rsclustercon->ssl, buf, 1024 - 1)) > 0) {
191 buf[bytes] = 0;
192 char* newreply;
193 if ((newreply=(char*)realloc(reply,strlen(reply)+bytes+1))==NULL) {
194 perror("Unable to allocate reply buffer");
195 free(reply);
196 return NULL;
197 } else
198 reply = newreply;
199 strcat(reply, buf);
200 }
201
202 /* Remove HTTP headers */
203 char* http_body;
204 char* retval_txt;
205 if (NULL==(http_body = strstr(reply,"\r\n\r\n")))
206 retval_txt= NULL;
207 else
208 retval_txt=strdup(http_body);
209 free(reply);
210
211 cJSON* retval_json = cJSON_Parse(retval_txt);
212 free(retval_txt);
213
214 return retval_json;
215}
216
217void cluster_close(rsclustercon_t* rsclustercon) {
218 SSL_shutdown(rsclustercon->ssl);
219 SSL_free(rsclustercon->ssl);
220 close(rsclustercon->sock);
221 SSL_CTX_free(rsclustercon->ctx);
222 EVP_cleanup();
223}
224
225void cluster_del(rsclustercon_t* rsclustercon) {
226 free(rsclustercon->cacert);
227 free(rsclustercon->pass);
228 free(rsclustercon->user);
229 free(rsclustercon->host);
230 free(rsclustercon);
231}
232
233/* vim: set tw=80: */
char * base64_encode(char *plain)
Encode a zero terminated C string in Base64.
Definition: base64.c:39
Simple Base64 encoding and decoding functions.
void cluster_close(rsclustercon_t *rsclustercon)
Definition: clustercon.c:217
struct rsclustercon_s rsclustercon_t
void cluster_del(rsclustercon_t *rsclustercon)
Definition: clustercon.c:225
rsclustercon_t * cluster_new(const cluster_t *cluster)
Definition: clustercon.c:49
int cluster_open(rsclustercon_t *rsclustercon)
Definition: clustercon.c:86
cJSON * cluster_queryget(const rsclustercon_t *rsclustercon, const char *endpoint)
Definition: clustercon.c:150
<+DETAILED+>
#define NULL
Definition: rsstats-opts.c:64
Definition: cJSON.h:103
char * host
Definition: cluster.h:26
char * insecure
Definition: cluster.h:29
char * pass
Definition: cluster.h:28
char * user
Definition: cluster.h:27
char * cacert
Definition: cluster.h:30
unsigned short int insecure
Definition: clustercon.c:42
char * cacert
Definition: clustercon.c:43
SSL_CTX * ctx
Definition: clustercon.c:45