1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
20 #include "sys_utils.h"
21 #include "log_utils.h"
33 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <arpa/inet.h>
37 #include <linux/if_link.h>
40 static char b64_encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
41 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
42 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
43 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
44 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
45 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
46 'w', 'x', 'y', 'z', '0', '1', '2', '3',
47 '4', '5', '6', '7', '8', '9', '+', '/'};
49 static char b64_decoding_table[256] = {0};
51 static int b64_mod_table[] = {0, 2, 1};
53 bool dir_exists(const char *path) {
57 return (stat(path, &st) != -1);
60 bool file_exists(const char *fname) {
63 return (access(fname, F_OK) != -1);
66 void file_touch(const char *fname, const char *content) {
69 FILE *f = fopen(fname, "w");
71 log_error("fopen failed\n");
76 fprintf(f, "%s", content);
81 char *file_read_content(const char *fname) {
86 FILE *f = fopen(fname, "rb");
88 fseek(f, 0, SEEK_END);
90 fseek(f, 0, SEEK_SET);
91 buffer = (char*)malloc(sizeof(char) * (length + 1));
93 fread(buffer, 1, length, f);
102 int get_int_from_string_with_default(const char *string, int default_value) {
104 int value = default_value;
107 rc = sscanf(string, "%d", &value);
109 value = default_value;
115 char *get_current_date_and_time(void) {
116 char *date_and_time = 0;
119 struct tm tm = *localtime(&t);
123 gettimeofday(&tv, 0);
124 millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
125 if(millisec>=1000) { // Allow for rounding up to nearest second
131 asprintf(&date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
132 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
133 tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
135 return date_and_time;
138 long int get_microseconds_since_epoch(void) {
143 gettimeofday(&tv, 0);
144 useconds = t*1000000 + tv.tv_usec; //add the microseconds to the seconds
150 bool get_local_ips(const char *ifname, char **ipv4, char **ipv6) {
156 struct ifaddrs *ifaddr;
158 char host[NI_MAXHOST];
164 if (getifaddrs(&ifaddr) == -1) {
166 goto get_local_ips_free;
169 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
170 if (ifa->ifa_addr == NULL) {
174 s = getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
175 if((strcmp(ifa->ifa_name, ifname) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
178 goto get_local_ips_free;
181 *ipv4 = strdup(host);
187 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
188 if (ifa->ifa_addr == NULL) {
192 s = getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in6),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
193 if((strcmp(ifa->ifa_name, ifname) == 0) && (ifa->ifa_addr->sa_family == AF_INET6)) {
196 goto get_local_ips_free;
199 *ipv6 = strdup(host);
216 bool check_port_open(const char *host, uint16_t port) {
219 int simpleSocket = 0;
220 int returnStatus = 0;
221 struct addrinfo simpleServer;
222 struct addrinfo *res;
224 memset(&simpleServer, 0, sizeof simpleServer);
225 simpleServer.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
226 simpleServer.ai_socktype = SOCK_STREAM;
227 simpleServer.ai_flags = AI_ADDRCONFIG;
230 sprintf(sport, "%d", port);
232 returnStatus = getaddrinfo(host, sport, &simpleServer, &res);
233 if(returnStatus != 0) {
237 simpleSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
238 if(simpleSocket < 0) {
243 char s[INET6_ADDRSTRLEN];
244 switch(res->ai_addr->sa_family) {
246 struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr;
247 inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
248 returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
253 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res->ai_addr;
254 inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
255 returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
265 if(returnStatus == 0) {
272 char *b64_encode(const uint8_t *data, size_t input_length) {
274 assert(input_length);
276 int output_length = 4 * ((input_length + 2) / 3);
278 char *encoded_data = (char *)malloc(sizeof(char) * (output_length + 1));
279 if (encoded_data == 0) {
283 for (int i = 0, j = 0; i < input_length;) {
284 uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
285 uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
286 uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
288 uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
290 encoded_data[j++] = b64_encoding_table[(triple >> 3 * 6) & 0x3F];
291 encoded_data[j++] = b64_encoding_table[(triple >> 2 * 6) & 0x3F];
292 encoded_data[j++] = b64_encoding_table[(triple >> 1 * 6) & 0x3F];
293 encoded_data[j++] = b64_encoding_table[(triple >> 0 * 6) & 0x3F];
296 for (int i = 0; i < b64_mod_table[input_length % 3]; i++) {
297 encoded_data[output_length - 1 - i] = '=';
300 encoded_data[output_length] = 0;
305 uint8_t *b64_decode(const char *data, size_t input_length, size_t *output_length) {
307 assert(input_length);
308 assert(output_length);
312 //one time compute decoding table
313 if(b64_decoding_table['A'] == 0) {
314 for(i = 0; i < 64; i++) {
315 b64_decoding_table[(unsigned char)b64_encoding_table[i]] = i;
319 if(input_length % 4 != 0) {
323 *output_length = input_length / 4 * 3;
324 if(data[input_length - 1] == '=') {
327 if(data[input_length - 2] == '=') {
331 uint8_t *decoded_data = (uint8_t*)malloc(*output_length + 1);
332 if(decoded_data == 0) {
336 for(i = 0, j = 0; i < input_length;) {
337 uint32_t sextet_a = data[i] == '=' ? 0 & i++ : b64_decoding_table[(int)data[i++]];
338 uint32_t sextet_b = data[i] == '=' ? 0 & i++ : b64_decoding_table[(int)data[i++]];
339 uint32_t sextet_c = data[i] == '=' ? 0 & i++ : b64_decoding_table[(int)data[i++]];
340 uint32_t sextet_d = data[i] == '=' ? 0 & i++ : b64_decoding_table[(int)data[i++]];
341 uint32_t triple = ( sextet_a << 3 * 6 ) + ( sextet_b << 2 * 6 ) + ( sextet_c << 1 * 6 ) + ( sextet_d << 0 * 6 );
343 if(j < *output_length) {
344 decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
347 if(j < *output_length) {
348 decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
351 if(j < *output_length) {
352 decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
359 char *str_replace(const char *orig, const char *rep, const char *with) {
364 char *result; // the return string
365 const char *ins; // the next insert point
367 int len_rep; // length of rep (the string to remove)
368 int len_with; // length of with (the string to replace rep with)
369 int len_front; // distance between rep and end of last rep
370 int count; // number of replacements
372 // sanity checks and initialization
377 len_rep = strlen(rep);
379 return 0; // empty rep causes infinite loop during count
385 len_with = strlen(with);
387 // count the number of replacements needed
389 for(count = 0; (tmp = strstr(ins, rep)); ++count) {
393 tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
399 // first time through the loop, all the variable are set correctly
401 // tmp points to the end of the result string
402 // ins points to the next occurrence of rep in orig
403 // orig points to the remainder of orig after "end of rep"
405 ins = strstr(orig, rep);
406 len_front = ins - orig;
407 tmp = strncpy(tmp, orig, len_front) + len_front;
408 tmp = strcpy(tmp, with) + len_with;
409 orig += len_front + len_rep; // move to next "end of rep"
416 char *read_key(const char *filename) {
423 char *key_string = 0;
425 fp = fopen(filename, "r");
427 log_error("could not open file %s\n", filename);
431 while((read = getline(&line, &len, fp)) != -1) {
432 // we ignore the first and last lines forPrivate keys, Public keys and Certificates
433 if(strstr(line, "PRIVATE KEY-----") || strstr(line, "PUBLIC KEY-----") || strstr(line, "CERTIFICATE-----")) {
441 key_string = (char *)realloc(key_string, strlen(key_string) + read + 1);
442 if(key_string == 0) {
443 log_error("bad allocation\n");
448 strcat(key_string, line);
451 key_string = strdup(line);
452 if(key_string == 0) {
453 log_error("bad allocation\n");
473 void vsftp_daemon_init(void) {
474 system("/usr/sbin/vsftpd &");
477 void vsftp_daemon_deinit(void) {
478 system("killall -9 vsftpd");
481 void sftp_daemon_init(void) {
482 system("/usr/sbin/sshd -D &");
485 void sftp_daemon_deinit(void) {
486 system("killall -9 sshd");