diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..bd1c578c83ad14858aad02c39306f3cf5328bc36 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,18 @@ +stages: + - prepare + - analyze + - build + - test + +variables: + GIT_SUBMODULE_STRATEGY: normal + +cellframe-sdk-analyze: + stage: analyze + tags: + - cellframe-sdk + script: ~/production/integration/PVS-studio/analyze.sh + artifacts: + paths: + - report/issues.txt + when: always diff --git a/3rdparty/wepoll/wepoll.c b/3rdparty/wepoll/wepoll.c index 651673aad37227314985327a42f6d94790fdb653..6b5e8c6ba1e6dad8d47983e7dfbeb91f913d0aac 100644 --- a/3rdparty/wepoll/wepoll.c +++ b/3rdparty/wepoll/wepoll.c @@ -136,9 +136,9 @@ WEPOLL_EXPORT int epoll_wait(HANDLE ephnd, #pragma warning(push, 1) #endif -#include <WS2tcpip.h> -#include <WinSock2.h> -#include <Windows.h> +#include <ws2tcpip.h> +#include <winsock2.h> +#include <windows.h> #ifndef __GNUC__ #pragma warning(pop) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8ab298486152842388a0616cc148ffd7c142227..61a81f20584496b93acb229992865dedb54180b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ add_subdirectory(dap-sdk) add_subdirectory(3rdparty/monero_crypto) add_subdirectory(3rdparty/cuttdb) add_subdirectory(modules/) +add_subdirectory(modules_dynamic) add_library(${PROJECT_NAME} STATIC cellframe-sdk.c) @@ -123,6 +124,12 @@ if (CELLFRAME_MODULES MATCHES "srv-stake") set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_stake ) endif() +# Enable service for dynamic modules +if (CELLFRAME_MODULES MATCHES "modules-dynamic") + message("[+] Module 'dap_modules_dynamic_cdb'") + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_modules_dynamic_cdb ) +endif() + if (WIN32) set(CELLFRAME_LIBS ${CELLFRAME_LIBS} KERNEL32 USER32 SHELL32 WINMM GDI32 ADVAPI32 Ole32 Version Imm32 OleAut32 ws2_32 ntdll psapi diff --git a/dap-sdk/core/include/dap_file_utils.h b/dap-sdk/core/include/dap_file_utils.h index 9bc55055d72e00a02bdfc5d0d30ac3cca3ab4060..d729966872df42ca6ac729e62441f344d80e281c 100755 --- a/dap-sdk/core/include/dap_file_utils.h +++ b/dap-sdk/core/include/dap_file_utils.h @@ -30,7 +30,7 @@ #ifdef _WIN32 -#include <Windows.h> +#include <windows.h> /* On Win32, the canonical directory separator is the backslash, and * the search path separator is the semicolon. Note that also the @@ -66,6 +66,10 @@ typedef struct dap_list_name_directories{ * @dir_path directory pathname * @return true, if the directory path contains only ASCII symbols */ +#ifdef __cplusplus +extern "C" { +#endif + bool dap_valid_ascii_symbols(const char *a_dir_path); /** @@ -111,4 +115,8 @@ dap_list_name_directories_t *dap_get_subs(const char *a_path_name); */ bool dap_file_get_contents(const char *filename, char **contents, size_t *length); +#ifdef __cplusplus +} +#endif + #endif // _FILE_UTILS_H_ diff --git a/dap-sdk/core/include/dap_fnmatch.h b/dap-sdk/core/include/dap_fnmatch.h new file mode 100644 index 0000000000000000000000000000000000000000..9afaba94581823c6ae1c909b7d18cce9a712c2b5 --- /dev/null +++ b/dap-sdk/core/include/dap_fnmatch.h @@ -0,0 +1,62 @@ +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in <unistd.h>. */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + `fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +/* Match NAME against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int dap_fnmatch (const char *__pattern, const char *__name, int __flags); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/dap-sdk/core/include/dap_fnmatch_loop.h b/dap-sdk/core/include/dap_fnmatch_loop.h new file mode 100644 index 0000000000000000000000000000000000000000..550b5d80164380aea6aecbb092cd3dcbf60004c1 --- /dev/null +++ b/dap-sdk/core/include/dap_fnmatch_loop.h @@ -0,0 +1,1223 @@ +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include "dap_fnmatch.h" + +struct STRUCT +{ + const char *pattern; + const char *string; + int no_leading_period; +}; + +#define L_func(CS) CS +/* Global variable. */ +static int posixly_correct; +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int FCT (const char *pattern, const char *string, + const char *string_end, int no_leading_period, int flags, + struct STRUCT *ends, size_t alloca_used); +static int EXT (int opt, const char *pattern, const char *string, + const char *string_end, int no_leading_period, int flags, + size_t alloca_used); +static const char *END (const char *patternp); + +static int +FCT (const char *pattern, const char *string, const char *string_end, + int no_leading_period, int flags, struct STRUCT *ends, size_t alloca_used) +{ + const char *p = pattern, *n = string; + unsigned char c; +#ifdef _LIBC +# if WIDE_CHAR_VERSION + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); +# else + const unsigned char *collseq = (const unsigned char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); +# endif +#endif + + while ((c = *p++) != '\0') + { + int new_no_leading_period = 0; + c = FOLD (c); + + switch (c) + { + case '?': + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res = EXT (c, p, n, string_end, no_leading_period, + flags, alloca_used); + if (res != -1) + return res; + } + + if (n == string_end) + return FNM_NOMATCH; + else if (*n == '/' && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == '.' && no_leading_period) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (n == string_end || FOLD ((unsigned char) *n) != c) + return FNM_NOMATCH; + break; + + case '*': + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res = EXT (c, p, n, string_end, no_leading_period, + flags, alloca_used); + if (res != -1) + return res; + } + else if (ends != NULL) + { + ends->pattern = p - 1; + ends->string = n; + ends->no_leading_period = no_leading_period; + return 0; + } + + if (n != string_end && *n == '.' && no_leading_period) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if (*p == '(' && (flags & FNM_EXTMATCH) != 0) + { + const char *endp = END (p); + if (endp != p) + { + /* This is a pattern. Skip over it. */ + p = endp; + continue; + } + } + + if (c == '?') + { + /* A ? needs to match one character. */ + if (n == string_end) + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else if (*n == '/' + && __builtin_expect (flags & FNM_FILE_NAME, 0)) + /* A slash does not match a wildcard under + FNM_FILE_NAME. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this means it cannot match, unless the FNM_LEADING_DIR + flag is set. */ + { + int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; + + if (flags & FNM_FILE_NAME) + { + if (flags & FNM_LEADING_DIR) + result = 0; + else + { + if (MEMCHR (n, '/', string_end - n) == NULL) + result = 0; + } + } + + return result; + } + else + { + const char *endp; + struct STRUCT end; + + end.pattern = NULL; + endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? '/' : '\0', + string_end - n); + if (endp == NULL) + endp = string_end; + + if (c == '[' + || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 + && (c == '@' || c == '+' || c == '!') + && *p == '(')) + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + for (--p; n < endp; ++n, no_leading_period = 0) + if (FCT (p, n, string_end, no_leading_period, flags2, + &end, alloca_used) == 0) + goto found; + } + else if (c == '/' && (flags & FNM_FILE_NAME)) + { + while (n < string_end && *n != '/') + ++n; + if (n < string_end && *n == '/' + && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags, + NULL, alloca_used) == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n, no_leading_period = 0) + if (FOLD ((unsigned char) *n) == c + && (FCT (p, n, string_end, no_leading_period, flags2, + &end, alloca_used) == 0)) + { + found: + if (end.pattern == NULL) + return 0; + break; + } + if (end.pattern != NULL) + { + p = end.pattern; + n = end.string; + no_leading_period = end.no_leading_period; + continue; + } + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + const char *p_init = p; + const char *n_init = n; + int not; + char cold; + unsigned char fn; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (n == string_end) + return FNM_NOMATCH; + + if (*n == '.' && no_leading_period) + return FNM_NOMATCH; + + if (*n == L_func('/') && (flags & FNM_FILE_NAME)) + /* `/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == '!' || (posixly_correct < 0 && *p == '^')); + if (not) + ++p; + + fn = FOLD ((unsigned char) *n); + + c = *p++; + for (;;) + { + if (!(flags & FNM_NOESCAPE) && c == L_func('\\')) + { + if (*p == L_func('\0')) + return FNM_NOMATCH; + c = FOLD ((unsigned char) *p); + ++p; + + goto normal_bracket; + } + else if (c == L_func('[') && *p == L_func(':')) + { + /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wctype_t wt; +#endif + const char *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == L_func(':') && p[1] == L_func(']')) + { + p += 2; + break; + } + if (c < L_func('a') || c >= L_func('z')) + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = L_func('['); + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = L_func('\0'); + +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + +# if defined _LIBC && ! WIDE_CHAR_VERSION + /* The following code is glibc specific but does + there a good job in speeding up the code since + we can avoid the btowc() call. */ + if (_ISCTYPE ((unsigned char) *n, wt)) + goto matched; +# else + if (ISWCTYPE (BTOWC ((unsigned char) *n), wt)) + goto matched; +# endif +#else + if ((STREQ (str, L_func("alnum")) && ISALNUM ((unsigned char) *n)) + || (STREQ (str, L_func("alpha")) && ISALPHA ((unsigned char) *n)) + || (STREQ (str, L_func("blank")) && ISBLANK ((unsigned char) *n)) + || (STREQ (str, L_func("cntrl")) && ISCNTRL ((unsigned char) *n)) + || (STREQ (str, L_func("digit")) && ISDIGIT ((unsigned char) *n)) + || (STREQ (str, L_func("graph")) && ISGRAPH ((unsigned char) *n)) + || (STREQ (str, L_func("lower")) && ISLOWER ((unsigned char) *n)) + || (STREQ (str, L_func("print")) && ISPRINT ((unsigned char) *n)) + || (STREQ (str, L_func("punct")) && ISPUNCT ((unsigned char) *n)) + || (STREQ (str, L_func("space")) && ISSPACE ((unsigned char) *n)) + || (STREQ (str, L_func("upper")) && ISUPPER ((unsigned char) *n)) + || (STREQ (str, L_func("xdigit")) && ISXDIGIT ((unsigned char) *n))) + goto matched; +#endif + c = *p++; + } +#ifdef _LIBC + else if (c == L_func('[') && *p == L_func('=')) + { + /* It's important that STR be a scalar variable rather + than a one-element array, because GCC (at least 4.9.2 + -O2 on x86-64) can be confused by the array and + diagnose a "used initialized" in a dead branch in the + findidx function. */ + unsigned char str; + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const char *startp = p; + + c = *++p; + if (c == L_func('\0')) + { + p = startp; + c = L_func('['); + goto normal_bracket; + } + str = c; + + c = *++p; + if (c != L_func('=') || p[1] != L_func(']')) + { + p = startp; + c = L_func('['); + goto normal_bracket; + } + p += 2; + + if (nrules == 0) + { + if ((unsigned char) *n == str) + goto matched; + } + else + { + const int32_t *table; +# if WIDE_CHAR_VERSION + const int32_t *weights; + const wint_t *extra; +# else + const unsigned char *weights; + const unsigned char *extra; +# endif + const int32_t *indirect; + int32_t idx; + const unsigned char *cp = (const unsigned char *) &str; + +# if WIDE_CHAR_VERSION + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const wint_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); +# else + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); +# endif + + idx = FINDIDX (table, indirect, extra, &cp, 1); + if (idx != 0) + { + /* We found a table entry. Now see whether the + character we are currently at has the same + equivalance class value. */ + int len = weights[idx & 0xffffff]; + int32_t idx2; + const unsigned char *np = (const unsigned char *) n; + + idx2 = FINDIDX (table, indirect, extra, + &np, string_end - n); + if (idx2 != 0 + && (idx >> 24) == (idx2 >> 24) + && len == weights[idx2 & 0xffffff]) + { + int cnt = 0; + + idx &= 0xffffff; + idx2 &= 0xffffff; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto matched; + } + } + } + + c = *p++; + } +#endif + else if (c == L_func('\0')) + { + /* [ unterminated, treat as normal character. */ + p = p_init; + n = n_init; + c = L_func('['); + goto normal_match; + } + else + { + int is_range = 0; + +#ifdef _LIBC + int is_seqval = 0; + + if (c == L_func('[') && *p == L_func('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const char *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_func('.') && p[1] == L_func(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = *p == L_func('-') && p[1] != L_func('\0'); + + if (nrules == 0) + { + /* There are no names defined in the collation + data. Therefore we only accept the trivial + names consisting of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + { + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; +# if WIDE_CHAR_VERSION + char *wextra; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element. */ + idx += 1 + extra[idx]; +# if WIDE_CHAR_VERSION + /* Skip the byte sequence of the + collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (char *) &extra[idx + 4]; + + if (/* Compare the length of the sequence. */ + c1 == wextra[0] + /* Compare the wide char sequence. */ + && WMEMCMP (startp + 1, &wextra[1], + c1) == 0) + /* Yep, this is the entry. */ + break; +# else + if (/* Compare the length of the sequence. */ + c1 == extra[idx] + /* Compare the byte sequence. */ + && memcmp (startp + 1, + &extra[idx + 1], c1) == 0) + /* Yep, this is the entry. */ + break; +# endif + } + + if (elem < table_size) + { + /* Compare the byte sequence but only if + this is not part of a range. */ + if (! is_range + +# if WIDE_CHAR_VERSION + && WMEMCMP (n, &wextra[1], c1) == 0 +# else + && memcmp (n, &extra[idx + 1], c1) == 0 +# endif + ) + { + n += c1 - 1; + goto matched; + } + + /* Get the collation sequence value. */ + is_seqval = 1; +# if WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; +# else + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + cold = *((int32_t *) &extra[idx]); +# endif + + c = *p++; + } + else if (c1 == 1) + { + /* No valid character. Match it as a + single byte. */ + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else +#endif + { + c = FOLD (c); + normal_bracket: + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = (*p == L_func('-') && p[1] != L_func('\0') + && p[1] != L_func(']')); + + if (!is_range && c == fn) + goto matched; + + /* This is needed if we goto normal_bracket; from + outside of is_seqval's scope. */ + //is_seqval = 0; + cold = c; + c = *p++; + } + + if (c == L_func('-') && *p != L_func(']')) + { +#if _LIBC + /* We have to find the collation sequence + value for C. Collation sequence is nothing + we can regularly access. The sequence + value is defined by the order in which the + definitions of the collation values for the + various characters appear in the source + file. A strange concept, nowhere + documented. */ + uint32_t fcollseq; + uint32_t lcollseq; + unsigned char cend = *p++; + +# if WIDE_CHAR_VERSION + /* Search in the `names' array for the characters. */ + fcollseq = __collseq_table_lookup (collseq, fn); + if (fcollseq == ~((uint32_t) 0)) + /* XXX We don't know anything about the character + we are supposed to match. This means we are + failing. */ + goto range_not_matched; + + if (is_seqval) + lcollseq = cold; + else + lcollseq = __collseq_table_lookup (collseq, cold); +# else + fcollseq = collseq[fn]; + lcollseq = is_seqval ? cold : collseq[(unsigned char) cold]; +# endif + + is_seqval = 0; + if (cend == L_func('[') && *p == L_func('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_NRULES); + const char *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_func('.') && p[1] == L_func(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + if (nrules == 0) + { + /* There are no names defined in the + collation data. Therefore we only + accept the trivial names consisting + of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + cend = startp[1]; + } + else + { + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; +# if WIDE_CHAR_VERSION + char *wextra; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating + element. */ + idx += 1 + extra[idx]; +# if WIDE_CHAR_VERSION + /* Skip the byte sequence of the + collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (char *) &extra[idx + 4]; + + if (/* Compare the length of the + sequence. */ + c1 == wextra[0] + /* Compare the wide char sequence. */ + && WMEMCMP (startp + 1, &wextra[1], + c1) == 0) + /* Yep, this is the entry. */ + break; +# else + if (/* Compare the length of the + sequence. */ + c1 == extra[idx] + /* Compare the byte sequence. */ + && memcmp (startp + 1, + &extra[idx + 1], c1) == 0) + /* Yep, this is the entry. */ + break; +# endif + } + + if (elem < table_size) + { + /* Get the collation sequence value. */ + is_seqval = 1; +# if WIDE_CHAR_VERSION + cend = wextra[1 + wextra[idx]]; +# else + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + cend = *((int32_t *) &extra[idx]); +# endif + } + else if (c1 == 1) + { + cend = startp[1]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else + { + if (!(flags & FNM_NOESCAPE) && cend == L_func('\\')) + cend = *p++; + if (cend == L_func('\0')) + return FNM_NOMATCH; + cend = FOLD (cend); + } + + /* XXX It is not entirely clear to me how to handle + characters which are not mentioned in the + collation specification. */ + if ( +# if WIDE_CHAR_VERSION + lcollseq == 0xffffffff || +# endif + lcollseq <= fcollseq) + { + /* We have to look at the upper bound. */ + uint32_t hcollseq; + + if (is_seqval) + hcollseq = cend; + else + { +# if WIDE_CHAR_VERSION + hcollseq = + __collseq_table_lookup (collseq, cend); + if (hcollseq == ~((uint32_t) 0)) + { + /* Hum, no information about the upper + bound. The matching succeeds if the + lower bound is matched exactly. */ + if (lcollseq != fcollseq) + goto range_not_matched; + + goto matched; + } +# else + hcollseq = collseq[cend]; +# endif + } + + if (lcollseq <= hcollseq && fcollseq <= hcollseq) + goto matched; + } +# if WIDE_CHAR_VERSION + range_not_matched: +# endif +#else + /* We use a boring value comparison of the character + values. This is better than comparing using + `strcoll' since the latter would have surprising + and sometimes fatal consequences. */ + unsigned char cend = *p++; + + if (!(flags & FNM_NOESCAPE) && cend == L_func('\\')) + cend = *p++; + if (cend == L_func('\0')) + return FNM_NOMATCH; + + /* It is a range. */ + if (cold <= fn && fn <= cend) + goto matched; +#endif + + c = *p++; + } + } + + if (c == L_func(']')) + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + while ((c = *p++) != L_func (']')) + { + if (c == L_func('\0')) + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + if (!(flags & FNM_NOESCAPE) && c == L_func('\\')) + { + if (*p == L_func('\0')) + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == L_func('[') && *p == L_func(':')) + { + int c1 = 0; + const char *startp = p; + + while (1) + { + c = *++p; + if (++c1 == CHAR_CLASS_MAX_LENGTH) + return FNM_NOMATCH; + + if (*p == L_func(':') && p[1] == L_func(']')) + break; + + if (c < L_func('a') || c >= L_func('z')) + { + p = startp - 2; + break; + } + } + p += 2; + } + else if (c == L_func('[') && *p == L_func('=')) + { + c = *++p; + if (c == L_func('\0')) + return FNM_NOMATCH; + c = *++p; + if (c != L_func('=') || p[1] != L_func(']')) + return FNM_NOMATCH; + p += 2; + } + else if (c == L_func('[') && *p == L_func('.')) + { + while (1) + { + c = *++p; + if (c == L_func('\0')) + return FNM_NOMATCH; + + if (c == L_func('.') && p[1] == L_func(']')) + break; + } + p += 2; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + case L_func('+'): + case L_func('@'): + case L_func('!'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res = EXT (c, p, n, string_end, no_leading_period, flags, + alloca_used); + if (res != -1) + return res; + } + goto normal_match; + + case L_func('/'): + if (NO_LEADING_PERIOD (flags)) + { + if (n == string_end || c != (unsigned char) *n) + return FNM_NOMATCH; + + new_no_leading_period = 1; + break; + } + /* FALLTHROUGH */ + default: + normal_match: + if (n == string_end || c != FOLD ((unsigned char) *n)) + return FNM_NOMATCH; + } + + no_leading_period = new_no_leading_period; + ++n; + } + + if (n == string_end) + return 0; + + if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_func('/')) + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + + +const char * +END (const char *pattern) +{ + const char *p = pattern; + + while (1) + if (*++p == L_func('\0')) + /* This is an invalid pattern. */ + return pattern; + else if (*p == L_func('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_func('!') || (posixly_correct < 0 && *p == L_func('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_func(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_func(']')) + if (*p++ == L_func('\0')) + /* This is no valid pattern. */ + return pattern; + } + else if ((*p == L_func('?') || *p == L_func('*') || *p == L_func('+') || *p == L_func('@') + || *p == L_func('!')) && p[1] == L_func('(')) + { + p = END (p + 1); + if (*p == L_func('\0')) + /* This is an invalid pattern. */ + return pattern; + } + else if (*p == L_func(')')) + break; + + return p + 1; +} + + +static int +EXT (int opt, const char *pattern, const char *string, const char *string_end, + int no_leading_period, int flags, size_t alloca_used) +{ + const char *startp; + int level; + struct patternlist + { + struct patternlist *next; + char malloced; + char str[0]; + } *list = NULL; + struct patternlist **lastp = &list; + size_t pattern_len = STRLEN (pattern); + int any_malloced = 0; + const char *p; + const char *rs; + int retval = 0; + + /* Parse the pattern. Store the individual parts in the list. */ + level = 0; + for (startp = p = pattern + 1; level >= 0; ++p) + if (*p == L_func('\0')) + { + /* This is an invalid pattern. */ + retval = -1; + goto out; + } + else if (*p == L_func('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_func('!') || (posixly_correct < 0 && *p == L_func('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_func(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_func(']')) + if (*p++ == L_func('\0')) + { + /* This is no valid pattern. */ + retval = -1; + goto out; + } + } + else if ((*p == L_func('?') || *p == L_func('*') || *p == L_func('+') || *p == L_func('@') + || *p == L_func('!')) && p[1] == L_func('(')) + /* Remember the nesting level. */ + ++level; + else if (*p == L_func(')')) + { + if (level-- == 0) + { + /* This means we found the end of the pattern. */ +#define NEW_PATTERN \ + struct patternlist *newp; \ + size_t slen = (opt == '?' || opt == '@' \ + ? pattern_len : (p - startp + 1)); \ + slen = sizeof (struct patternlist) + (slen * sizeof (char)); \ + int malloced = ! __libc_use_alloca (alloca_used + slen); \ + if (__builtin_expect (malloced, 0)) \ + { \ + newp = malloc (slen); \ + if (newp == NULL) \ + { \ + retval = -2; \ + goto out; \ + } \ + any_malloced = 1; \ + } \ + else \ + newp = alloca_account (slen, alloca_used); \ + newp->next = NULL; \ + newp->malloced = malloced; \ + *((char *) MEMPCPY (newp->str, startp, p - startp)) = L_func('\0'); \ + *lastp = newp; \ + lastp = &newp->next + NEW_PATTERN; + } + } + else if (*p == L_func('|')) + { + if (level == 0) + { + NEW_PATTERN; + startp = p + 1; + } + } + assert (list != NULL); + assert (p[-1] == L_func(')')); +#undef NEW_PATTERN + + switch (opt) + { + case '*': + if (FCT (p, string, string_end, no_leading_period, flags, NULL, + alloca_used) == 0) + goto success; + /* FALLTHROUGH */ + + case '+': + do + { + for (rs = string; rs <= string_end; ++rs) + /* First match the prefix with the current pattern with the + current pattern. */ + if (FCT (list->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0 + /* This was successful. Now match the rest with the rest + of the pattern. */ + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0 + /* This didn't work. Try the whole pattern. */ + || (rs != string + && FCT (pattern - 1, rs, string_end, + rs == string + ? no_leading_period + : (rs[-1] == '/' && NO_LEADING_PERIOD (flags) + ? 1 : 0), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD, NULL, + alloca_used) == 0))) + /* It worked. Signal success. */ + goto success; + } + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + retval = FNM_NOMATCH; + break; + + case '?': + if (FCT (p, string, string_end, no_leading_period, flags, NULL, + alloca_used) == 0) + goto success; + /* FALLTHROUGH */ + + case '@': + do { + /* I cannot believe it but `strcat' is actually acceptable + here. Match the entire string with the prefix from the + pattern list and the rest of the pattern following the + pattern list. */ + if(FCT(STRCAT(list->str, p), string, string_end, + no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0) + /* It worked. Signal success. */ + goto success; + } while((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + retval = FNM_NOMATCH; + break; + + case '!': + for (rs = string; rs <= string_end; ++rs) + { + struct patternlist *runp; + + for (runp = list; runp != NULL; runp = runp->next) + if (FCT (runp->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0) + break; + + /* If none of the patterns matched see whether the rest does. */ + if (runp == NULL + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0)) + /* This is successful. */ + goto success; + } + + /* None of the patterns together with the rest of the pattern + lead to a match. */ + retval = FNM_NOMATCH; + break; + + default: + assert (! "Invalid extended matching operator"); + retval = -1; + break; + } + + success: + out: + if (any_malloced) + while (list != NULL) + { + struct patternlist *old = list; + list = list->next; + if (old->malloced) + free (old); + } + + return retval; +} + + +#undef FOLD +#undef FCT +#undef EXT +#undef END +#undef STRUCT +#undef MEMPCPY +#undef MEMCHR +#undef STRCOLL +#undef STRLEN +#undef STRCAT +#undef L +#undef BTOWC +#undef WIDE_CHAR_VERSION +#undef FINDIDX diff --git a/dap-sdk/core/include/dap_strfuncs.h b/dap-sdk/core/include/dap_strfuncs.h index c581294cb9df00d18df510e4425c3e4f8787414e..79f00942eaeb5050de51017e3d9ab36b2cd165e6 100755 --- a/dap-sdk/core/include/dap_strfuncs.h +++ b/dap-sdk/core/include/dap_strfuncs.h @@ -13,6 +13,7 @@ #include <string.h> #include "dap_math_ops.h" +#include "dap_fnmatch.h" #define dap_return_if_fail(expr) {if(!(expr)) {return;}} #define dap_return_val_if_fail(expr,val) {if(!(expr)) {return (val);}} diff --git a/dap-sdk/core/src/dap_common.c b/dap-sdk/core/src/dap_common.c index c4edcbb8a62a8060a07eb475f1f2d1d03105846a..ea8ffebd01d7250b93e8f5aae6ed0f936c6efa63 100755 --- a/dap-sdk/core/src/dap_common.c +++ b/dap-sdk/core/src/dap_common.c @@ -21,6 +21,7 @@ You should have received a copy of the GNU General Public License along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ +#define _POSIX_THREAD_SAFE_FUNCTIONS #include <stdio.h> #include <stdlib.h> #include <time.h> /* 'nanosleep' */ @@ -331,16 +332,21 @@ void _log_it(const char *a_log_tag, enum dap_log_level a_ll, const char *a_fmt, if ( a_ll < s_dap_log_level || a_ll >= 16 || !a_log_tag ) return; log_str_t *l_log_string = DAP_NEW_Z(log_str_t); - strncpy(l_log_string->str, s_ansi_seq_color[a_ll],sizeof (l_log_string->str)-1); + size_t offset2 = sizeof(l_log_string->str) - 2; + strncpy(l_log_string->str, s_ansi_seq_color[a_ll], offset2); l_log_string->offset = s_ansi_seq_color_len[a_ll]; s_update_log_time(l_log_string->str + l_log_string->offset); size_t offset = strlen(l_log_string->str); - offset += dap_snprintf(l_log_string->str + offset, sizeof (l_log_string->str) -offset, "%s[%s%s", s_log_level_tag[a_ll], a_log_tag, "] "); + offset += dap_snprintf(l_log_string->str + offset, offset2, "%s[%s%s", s_log_level_tag[a_ll], a_log_tag, "] "); + offset2 -= offset; va_list va; va_start( va, a_fmt ); - offset += dap_vsnprintf(l_log_string->str + offset,sizeof (l_log_string->str) -offset, a_fmt, va); + size_t l_offset = dap_vsnprintf(l_log_string->str + offset, offset2, a_fmt, va); + offset = (l_offset < offset2) ? offset + l_offset : offset; + offset2 = (l_offset < offset2) ? offset2 - offset : 0; va_end( va ); - memcpy(&l_log_string->str[offset], "\n", 1); + char *dummy = (offset2 == 0) ? memcpy(&l_log_string->str[sizeof(l_log_string->str) - 6], "...\n\0", 5) + : memcpy(&l_log_string->str[offset], "\n", 1); pthread_mutex_lock(&s_log_mutex); DL_APPEND(s_log_buffer, l_log_string); ++s_log_count; diff --git a/dap-sdk/core/src/dap_file_utils.c b/dap-sdk/core/src/dap_file_utils.c index 8a666b8900eaafa1ad63be8eb47083da5f3b3b94..db0b71c5849f498fc4dce44096e27631fffaf066 100755 --- a/dap-sdk/core/src/dap_file_utils.c +++ b/dap-sdk/core/src/dap_file_utils.c @@ -120,14 +120,15 @@ bool dap_dir_test(const char * a_dir_path) */ int dap_mkdir_with_parents(const char *a_dir_path) { - - char *path, *p; // validation of a pointer if(a_dir_path == NULL || a_dir_path[0] == '\0') { errno = EINVAL; return -1; } - path = strdup(a_dir_path); + char path[strlen(a_dir_path) + 1]; + memset(path, '\0', strlen(a_dir_path) + 1); + memcpy(path, a_dir_path, strlen(a_dir_path)); + char *p; // skip the root component if it is present, i.e. the "/" in Unix or "C:\" in Windows #ifdef _WIN32 if(((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z')) @@ -158,7 +159,6 @@ int dap_mkdir_with_parents(const char *a_dir_path) int result = mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); #endif if(result == -1) { - free(path); errno = ENOTDIR; return -1; } @@ -169,8 +169,6 @@ int dap_mkdir_with_parents(const char *a_dir_path) p++; } } while(p); - - free(path); return 0; } diff --git a/dap-sdk/core/src/dap_fnmatch.c b/dap-sdk/core/src/dap_fnmatch.c new file mode 100644 index 0000000000000000000000000000000000000000..f89fa536eff2959625980c269d6dd60e5f42d784 --- /dev/null +++ b/dap-sdk/core/src/dap_fnmatch.c @@ -0,0 +1,435 @@ +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include "dap_fnmatch.h" + + + +/* For platform which support the ISO C amendement 1 functionality we + support user defined character classes. */ +/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ +//# include <wchar.h> +//# include <wctype.h> + +# define __libc_use_alloca(n) false +# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0) +# define extend_alloca_account(buf, len, newlen, avar) \ + ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0) + + + +/* We need some of the locale data (the collation sequence information) + but there is no interface to get this information in general. Therefore + we support a correct implementation only in glibc. */ +#ifdef _LIBC +# include "../locale/localeinfo.h" +# include "../locale/coll-lookup.h" +# include <shlib-compat.h> + +# define CONCAT(a,b) __CONCAT(a,b) +# define mbsrtowcs __mbsrtowcs +# define fnmatch __fnmatch +extern int fnmatch (const char *pattern, const char *string, int flags); +#endif + +/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ +#define NO_LEADING_PERIOD(flags) \ + ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +//#if defined _LIBC || !defined __GNU_LIBRARY__ + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendement 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif + +# ifdef _LIBC +# define ISWCTYPE(WC, WT) __iswctype (WC, WT) +# else +# define ISWCTYPE(WC, WT) iswctype (WC, WT) +# endif + +# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC +/* In this case we are implementing the multibyte character handling. */ +# define HANDLE_MULTIBYTE 1 +# endif + +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + + +/* This function doesn't exist on most systems. */ + +# if !defined HAVE___STRCHRNUL && !defined _LIBC +static char * +__strchrnul (const char *s, int c) +{ + char *result = strchr (s, c); + if (result == NULL) + result = strchr (s, '\0'); + return result; +} +# endif + +# if HANDLE_MULTIBYTE && !defined HAVE___STRCHRNUL && !defined _LIBC +static wchar_t * +__wcschrnul (const wchar_t *s, wint_t c) +{ + wchar_t *result = wcschr (s, c); + if (result == NULL) + result = wcschr (s, '\0'); + return result; +} +# endif + +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) +# endif +# define FCT internal_fnmatch +# define EXT ext_match +# define END end_pattern +# define STRUCT fnmatch_struct +//# define L(CS) CS +# ifdef _LIBC +# define BTOWC(C) __btowc (C) +# else +# define BTOWC(C) btowc (C) +# endif +# define STRLEN(S) strlen(S) +# define STRCAT(D, S) strcat (D, S) +# define MEMPCPY(D, S, N) mempcpy (D, S, N) +# define MEMCHR(S, C, N) memchr (S, C, N) +# define STRCOLL(S1, S2) strcoll (S1, S2) +# define WIDE_CHAR_VERSION 0 +//# include <locale/weight.h> +# define FINDIDX findidx +# include "dap_fnmatch_loop.h" + + +# if HANDLE_MULTIBYTE +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? __towlower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? towlower (c) : (c)) +# endif +# define CHAR wchar_t +# define UCHAR wint_t +# define INT wint_t +# define FCT internal_fnwmatch +# define EXT ext_wmatch +# define END end_wpattern +# define STRUCT fnwmatch_struct +# define L(CS) L##CS +# define BTOWC(C) (C) +# define STRLEN(S) __wcslen (S) +# define STRCAT(D, S) __wcscat (D, S) +# define MEMPCPY(D, S, N) __wmempcpy (D, S, N) +# define MEMCHR(S, C, N) __wmemchr (S, C, N) +# define STRCOLL(S1, S2) wcscoll (S1, S2) +# ifdef _LIBC +# define WMEMCMP(S1, S2, N) __wmemcmp (S1, S2, N) +# else +# define WMEMCMP(S1, S2, N) wmemcmp (S1, S2, N) +# endif +# define WIDE_CHAR_VERSION 1 +/* Change the name the header defines so it doesn't conflict with + the <locale/weight.h> version included above. */ +# define findidx findidxwc +# include <locale/weightwc.h> +# undef findidx +# define FINDIDX findidxwc + +# undef IS_CHAR_CLASS +/* We have to convert the wide character string in a multibyte string. But + we know that the character class names consist of alphanumeric characters + from the portable character set, and since the wide character encoding + for a member of the portable character set is the same code point as + its single-byte encoding, we can use a simplified method to convert the + string to a multibyte character string. */ +static wctype_t +is_char_class (const wchar_t *wcs) +{ + char s[CHAR_CLASS_MAX_LENGTH + 1]; + char *cp = s; + + do + { + /* Test for a printable character from the portable character set. */ +# ifdef _LIBC + if (*wcs < 0x20 || *wcs > 0x7e + || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) + return (wctype_t) 0; +# else + switch (*wcs) + { + case L' ': case L'!': case L'"': case L'#': case L'%': + case L'&': case L'\'': case L'(': case L')': case L'*': + case L'+': case L',': case L'-': case L'.': case L'/': + case L'0': case L'1': case L'2': case L'3': case L'4': + case L'5': case L'6': case L'7': case L'8': case L'9': + case L':': case L';': case L'<': case L'=': case L'>': + case L'?': + case L'A': case L'B': case L'C': case L'D': case L'E': + case L'F': case L'G': case L'H': case L'I': case L'J': + case L'K': case L'L': case L'M': case L'N': case L'O': + case L'P': case L'Q': case L'R': case L'S': case L'T': + case L'U': case L'V': case L'W': case L'X': case L'Y': + case L'Z': + case L'[': case L'\\': case L']': case L'^': case L'_': + case L'a': case L'b': case L'c': case L'd': case L'e': + case L'f': case L'g': case L'h': case L'i': case L'j': + case L'k': case L'l': case L'm': case L'n': case L'o': + case L'p': case L'q': case L'r': case L's': case L't': + case L'u': case L'v': case L'w': case L'x': case L'y': + case L'z': case L'{': case L'|': case L'}': case L'~': + break; + default: + return (wctype_t) 0; + } +# endif + + /* Avoid overrunning the buffer. */ + if (cp == s + CHAR_CLASS_MAX_LENGTH) + return (wctype_t) 0; + + *cp++ = (char) *wcs++; + } + while (*wcs != L'\0'); + + *cp = '\0'; + +# ifdef _LIBC + return __wctype (s); +# else + return wctype (s); +# endif +} +# define IS_CHAR_CLASS(string) is_char_class (string) + +# include "fnmatch_loop.c" +# endif + + +int dap_fnmatch (const char *pattern, const char *string, int flags) +{ +# if HANDLE_MULTIBYTE + if (__builtin_expect (MB_CUR_MAX, 1) != 1) + { + mbstate_t ps; + size_t n; + const char *p; + wchar_t *wpattern_malloc = NULL; + wchar_t *wpattern; + wchar_t *wstring_malloc = NULL; + wchar_t *wstring; + size_t alloca_used = 0; + + /* Convert the strings into wide characters. */ + memset (&ps, '\0', sizeof (ps)); + p = pattern; +#ifdef _LIBC + n = __strnlen (pattern, 1024); +#else + n = strlen (pattern); +#endif + if (__glibc_likely (n < 1024)) + { + wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), + alloca_used); + n = mbsrtowcs (wpattern, &p, n + 1, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (p) + { + memset (&ps, '\0', sizeof (ps)); + goto prepare_wpattern; + } + } + else + { + prepare_wpattern: + n = mbsrtowcs (NULL, &pattern, 0, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) + { + __set_errno (ENOMEM); + return -2; + } + wpattern_malloc = wpattern + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); + assert (mbsinit (&ps)); + if (wpattern == NULL) + return -2; + (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps); + } + + assert (mbsinit (&ps)); +#ifdef _LIBC + n = __strnlen (string, 1024); +#else + n = strlen (string); +#endif + p = string; + if (__glibc_likely (n < 1024)) + { + wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), + alloca_used); + n = mbsrtowcs (wstring, &p, n + 1, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + { + /* Something wrong. + XXX Do we have to set `errno' to something which + mbsrtows hasn't already done? */ + free_return: + free (wpattern_malloc); + return -1; + } + if (p) + { + memset (&ps, '\0', sizeof (ps)); + goto prepare_wstring; + } + } + else + { + prepare_wstring: + n = mbsrtowcs (NULL, &string, 0, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + goto free_return; + if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) + { + free (wpattern_malloc); + __set_errno (ENOMEM); + return -2; + } + + wstring_malloc = wstring + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); + if (wstring == NULL) + { + free (wpattern_malloc); + return -2; + } + assert (mbsinit (&ps)); + (void) mbsrtowcs (wstring, &string, n + 1, &ps); + } + + int res = internal_fnwmatch (wpattern, wstring, wstring + n, + flags & FNM_PERIOD, flags, NULL, + alloca_used); + + free (wstring_malloc); + free (wpattern_malloc); + + return res; + } +# endif /* mbstate_t and mbsrtowcs or _LIBC. */ + + return internal_fnmatch (pattern, string, string + strlen (string), + flags & FNM_PERIOD, flags, NULL, 0); +} + +# ifdef _LIBC +# undef fnmatch +versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); +# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) +strong_alias (__fnmatch, __fnmatch_old) +compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); +# endif +libc_hidden_ver (__fnmatch, fnmatch) +# endif + +//#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/dap-sdk/core/test/rpmalloc/test/main.c b/dap-sdk/core/test/rpmalloc/test/main.c index f8fccef20dfb68072c7381ba149226f7367be704..a6e13766263e3aa7992e36f4865b228ee37b1ead 100644 --- a/dap-sdk/core/test/rpmalloc/test/main.c +++ b/dap-sdk/core/test/rpmalloc/test/main.c @@ -805,7 +805,7 @@ main(int argc, char** argv) { #endif #ifdef _WIN32 -#include <Windows.h> +#include <windows.h> static void test_initialize(void) { diff --git a/dap-sdk/core/test/rpmalloc/test/thread.c b/dap-sdk/core/test/rpmalloc/test/thread.c index 17b55035d1a54150db64cee553f516e9cf6f4850..21729f0c37b5e3dacdc8379605fe8147f74f922f 100644 --- a/dap-sdk/core/test/rpmalloc/test/thread.c +++ b/dap-sdk/core/test/rpmalloc/test/thread.c @@ -13,7 +13,7 @@ #endif #ifdef _WIN32 -# include <Windows.h> +# include <windows.h> # include <process.h> static unsigned __stdcall diff --git a/dap-sdk/core/test/rpmalloc/test/timer.c b/dap-sdk/core/test/rpmalloc/test/timer.c index 2ceb4b7ec9689ef6fe5118015d33fdc1e860c262..db138712d08966ce9b7630a726cfc47c08ae107f 100644 --- a/dap-sdk/core/test/rpmalloc/test/timer.c +++ b/dap-sdk/core/test/rpmalloc/test/timer.c @@ -2,7 +2,7 @@ #include <timer.h> #if defined(_WIN32) -# include <Windows.h> +# include <windows.h> #elif defined(__APPLE__) # include <mach/mach_time.h> static mach_timebase_info_data_t _time_info; diff --git a/dap-sdk/crypto/include/dap_cert.h b/dap-sdk/crypto/include/dap_cert.h index 9ba4e00ec17c8232b469a25c2c2e5e89f2b4e0d1..0dee3bf8858f543c7878ac73e8eaf341be497b25 100755 --- a/dap-sdk/crypto/include/dap_cert.h +++ b/dap-sdk/crypto/include/dap_cert.h @@ -82,6 +82,7 @@ void dap_cert_dump(dap_cert_t * a_cert); dap_pkey_t * dap_cert_to_pkey(dap_cert_t * a_cert); dap_cert_t * dap_cert_find_by_name(const char * a_cert_name); +dap_list_t *dap_cert_get_all_mem(); dap_sign_t * dap_cert_sign(dap_cert_t * a_cert, const void * a_data, size_t a_data_size, size_t a_output_size_wished ); diff --git a/dap-sdk/crypto/src/dap_cert.c b/dap-sdk/crypto/src/dap_cert.c index 5f5da67741246f0be603313d4a33cf54a2bc8c82..2916d19b6707d73da4597d8231f928bc3d99400e 100755 --- a/dap-sdk/crypto/src/dap_cert.c +++ b/dap-sdk/crypto/src/dap_cert.c @@ -300,6 +300,15 @@ dap_cert_t * dap_cert_find_by_name(const char * a_cert_name) } } +dap_list_t *dap_cert_get_all_mem() +{ + dap_list_t *l_ret = NULL; + dap_cert_item_t *l_cert_item = NULL, *l_cert_tmp; + HASH_ITER(hh, s_certs, l_cert_item, l_cert_tmp) { + l_ret = dap_list_append(l_ret, l_cert_item->cert); + } + return l_ret; +} /** * @brief dap_cert_new diff --git a/dap-sdk/crypto/src/dap_enc_dilithium.c b/dap-sdk/crypto/src/dap_enc_dilithium.c index 6d59b941887655b5b97393a19d6963add2914304..b8509aabdff1a00d12990ebdadc0c2ce8e426c08 100755 --- a/dap-sdk/crypto/src/dap_enc_dilithium.c +++ b/dap-sdk/crypto/src/dap_enc_dilithium.c @@ -40,9 +40,7 @@ void dap_enc_sig_dilithium_key_new_generate(struct dap_enc_key * key, const void int32_t retcode; - int dilithium_type = (seed && seed_size >= sizeof(uint8_t)) ? ((uint8_t*)seed)[0] % (DILITHIUM_MAX_SECURITY + 1) : - DILITHIUM_MIN_SIZE; - dap_enc_sig_dilithium_set_type(dilithium_type); + dap_enc_sig_dilithium_set_type(DILITHIUM_MAX_SPEED); //int32_t type = 2; diff --git a/dap-sdk/crypto/src/dap_enc_tesla.c b/dap-sdk/crypto/src/dap_enc_tesla.c index e8c03e6ba0521f801f9b1d178fc5b3eb1186f23c..07533bcf4b9def2b0ea65cfb2bb26bdea2c4e3bd 100755 --- a/dap-sdk/crypto/src/dap_enc_tesla.c +++ b/dap-sdk/crypto/src/dap_enc_tesla.c @@ -40,9 +40,7 @@ void dap_enc_sig_tesla_key_new_generate(struct dap_enc_key * key, const void *ke int32_t retcode; - int tesla_type = (seed && seed_size >= sizeof(uint8_t)) ? ((uint8_t*)seed)[0] % (PROVABLY_MAX_SECURITY + 1) : - HEURISTIC_MAX_SECURITY_AND_MAX_SPEED; - dap_enc_sig_tesla_set_type(tesla_type); + dap_enc_sig_tesla_set_type(HEURISTIC_MAX_SECURITY_AND_MAX_SPEED); /* type is a param of sign-security * type = 0 - Heuristic qTESLA, NIST's security category 1 diff --git a/dap-sdk/crypto/src/sig_picnic/picnic_impl.c b/dap-sdk/crypto/src/sig_picnic/picnic_impl.c index a98e7fd85aad97e5ece7c90c64a9939c91fc5125..2a0e25ffe8d35f7479ed5b1a189514bfbad34f7d 100755 --- a/dap-sdk/crypto/src/sig_picnic/picnic_impl.c +++ b/dap-sdk/crypto/src/sig_picnic/picnic_impl.c @@ -18,7 +18,7 @@ #include <string.h> #include <assert.h> #if defined (__WIN32) - #include <Windows.h> + #include <windows.h> #include <bcrypt.h> #elif defined (__APPLE__) #include "macos_specific_endian.h" diff --git a/dap-sdk/net/client/dap_client.c b/dap-sdk/net/client/dap_client.c index d33a1a96b022361521045842c2cecf0014d7db30..b799fe8080941db2ce65225fc546f9a3312f6650 100644 --- a/dap-sdk/net/client/dap_client.c +++ b/dap-sdk/net/client/dap_client.c @@ -138,7 +138,6 @@ void dap_client_set_active_channels (dap_client_t * a_client, const char * a_act DAP_CLIENT_PVT(a_client)->active_channels = dap_strdup( a_active_channels); } - /** * @brief dap_client_get_uplink_port * @param a_client @@ -149,6 +148,11 @@ uint16_t dap_client_get_uplink_port(dap_client_t * a_client) return DAP_CLIENT_PVT(a_client)->uplink_port; } +void dap_client_set_auth_cert(dap_client_t * a_client, dap_cert_t *a_cert) +{ + DAP_CLIENT_PVT(a_client)->auth_cert = a_cert; +} + /** * @brief dap_client_reset diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c index fd15bb670d5b3d5555dcf84e74164c65615503e2..1bb6f9708ef684d963df77157f6adcdb09724e0d 100644 --- a/dap-sdk/net/client/dap_client_pvt.c +++ b/dap-sdk/net/client/dap_client_pvt.c @@ -56,6 +56,7 @@ #include "dap_enc.h" #include "dap_common.h" #include "dap_strfuncs.h" +#include "dap_cert.h" //#include "dap_http_client_simple.h" #include "dap_client_http.h" @@ -396,25 +397,37 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt) case STAGE_STATUS_IN_PROGRESS: { switch (a_client_pvt->stage) { case STAGE_ENC_INIT: { - log_it(L_INFO, "Go to stage ENC: prepare the request"); - + log_it(L_INFO, "Go to stage ENC: prepare the request"); a_client_pvt->session_key_open = dap_enc_key_new_generate(DAP_ENC_KEY_TYPE_MSRLN, NULL, 0, NULL, 0, 0); - - size_t l_key_str_size_max = DAP_ENC_BASE64_ENCODE_SIZE(a_client_pvt->session_key_open->pub_key_data_size); - char *l_key_str = DAP_NEW_Z_SIZE(char, l_key_str_size_max + 1); + if (!a_client_pvt->session_key_open) { + log_it(L_ERROR, "Insufficient memory! May be a huge memory leak present"); + a_client_pvt->stage_status = STAGE_STATUS_ERROR; + break; + } + size_t l_key_size = a_client_pvt->session_key_open->pub_key_data_size; + dap_cert_t *l_cert = a_client_pvt->auth_cert; + dap_sign_t *l_sign = NULL; + size_t l_sign_size = 0; + if (l_cert) { + l_sign = dap_sign_create(l_cert->enc_key, a_client_pvt->session_key_open->pub_key_data, l_key_size, 0); + l_sign_size = dap_sign_get_size(l_sign); + } + uint8_t l_data[l_key_size + l_sign_size]; + memcpy(l_data, a_client_pvt->session_key_open->pub_key_data, l_key_size); + if (l_sign) { + memcpy(l_data + l_key_size, l_sign, l_sign_size); + } + size_t l_data_str_size_max = DAP_ENC_BASE64_ENCODE_SIZE(l_key_size + l_sign_size); + char l_data_str[l_data_str_size_max + 1]; // DAP_ENC_DATA_TYPE_B64_URLSAFE not need because send it by POST request - size_t l_key_str_enc_size = dap_enc_base64_encode(a_client_pvt->session_key_open->pub_key_data, - a_client_pvt->session_key_open->pub_key_data_size, - l_key_str, DAP_ENC_DATA_TYPE_B64); - - log_it(L_DEBUG, "ENC request size %u", l_key_str_enc_size); + size_t l_data_str_enc_size = dap_enc_base64_encode(l_data, l_key_size + l_sign_size, l_data_str, DAP_ENC_DATA_TYPE_B64); + log_it(L_DEBUG, "ENC request size %u", l_data_str_enc_size); int l_res = dap_client_pvt_request(a_client_pvt, DAP_UPLINK_PATH_ENC_INIT "/gd4y5yh78w42aaagh", - l_key_str, l_key_str_enc_size, m_enc_init_response, m_enc_init_error); + l_data_str, l_data_str_enc_size, m_enc_init_response, m_enc_init_error); // bad request if(l_res<0){ a_client_pvt->stage_status = STAGE_STATUS_ERROR; } - DAP_DELETE(l_key_str); } break; case STAGE_STREAM_CTL: { @@ -720,7 +733,7 @@ void dap_client_pvt_request_enc(dap_client_pvt_t * a_client_internal, const char , dap_client_callback_data_size_t a_response_proc , dap_client_callback_int_t a_response_error) { - bool is_query_enc = false; // it true, then encode a_query string + bool is_query_enc = true; // if true, then encode a_query string [Why do we even need this?] log_it(L_DEBUG, "Encrypted request: sub_url '%s' query '%s'", a_sub_url ? a_sub_url : "NULL", a_query ? a_query : "NULL"); size_t l_sub_url_size = a_sub_url ? strlen(a_sub_url) : 0; diff --git a/dap-sdk/net/client/include/dap_client.h b/dap-sdk/net/client/include/dap_client.h index 7a81af9734559fdf27c8efb458d548553c22a212..dc49c63796fc313f5084043988a51f75231ba117 100644 --- a/dap-sdk/net/client/include/dap_client.h +++ b/dap-sdk/net/client/include/dap_client.h @@ -28,6 +28,7 @@ #include "dap_events.h" #include "dap_stream.h" #include "dap_stream_ch.h" +#include "dap_cert.h" /** * @brief The dap_client_stage enum. Top level of client's state machine @@ -133,6 +134,7 @@ dap_stream_t * dap_client_get_stream(dap_client_t * a_client); dap_stream_ch_t * dap_client_get_stream_ch(dap_client_t * a_client, uint8_t a_ch_id); const char * dap_client_get_stream_id(dap_client_t * a_client); void dap_client_set_active_channels (dap_client_t * a_client, const char * a_active_channels); +void dap_client_set_auth_cert(dap_client_t * a_client, dap_cert_t *a_cert); dap_client_stage_t dap_client_get_stage(dap_client_t * a_client); dap_client_stage_status_t dap_client_get_stage_status(dap_client_t * a_client); diff --git a/dap-sdk/net/client/include/dap_client_pvt.h b/dap-sdk/net/client/include/dap_client_pvt.h index 9c93e03ad62ae463db9d407657e397b1d629810a..04aa7439242657964d7bd4bf8f5627aa36af1241 100644 --- a/dap-sdk/net/client/include/dap_client_pvt.h +++ b/dap-sdk/net/client/include/dap_client_pvt.h @@ -28,6 +28,8 @@ #include "dap_client.h" #include "dap_stream.h" #include "dap_events_socket.h" +#include "dap_cert.h" + typedef struct dap_enc_key dap_enc_key_t; typedef struct dap_http_client dap_http_client_t; @@ -47,7 +49,7 @@ typedef struct dap_client_internal dap_enc_key_t * session_key; // Symmetric private key for session encryption dap_enc_key_t * stream_key; // Stream private key for stream encryption char stream_id[25]; - + dap_cert_t *auth_cert; char * session_key_id; //void *curl;// curl connection descriptor diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/net/core/dap_events_socket.c index fb7f844171a219e8ca64d4e7de173810dba8a0f8..ca6769a0b385d94c90535bba528b199c475408db 100644 --- a/dap-sdk/net/core/dap_events_socket.c +++ b/dap-sdk/net/core/dap_events_socket.c @@ -324,7 +324,7 @@ void dap_events_socket_delete( dap_events_socket_t *a_es, bool preserve_inherito #endif } pthread_mutex_destroy(&a_es->write_hold); - free( a_es ); + DAP_DELETE( a_es ); } /** diff --git a/dap-sdk/net/core/dap_server.c b/dap-sdk/net/core/dap_server.c index b92ae2a8fb9f00538abd304f974eb122d49de956..3f47e681ec9f61d8287a676eb0a21113593c7687 100644 --- a/dap-sdk/net/core/dap_server.c +++ b/dap-sdk/net/core/dap_server.c @@ -517,9 +517,18 @@ static void read_write_cb( dap_client_remote_t *dap_cur, int32_t revents ) dap_cur->buf_out_size - total_sent, MSG_DONTWAIT | MSG_NOSIGNAL ); if( bytes_sent < 0 ) { - log_it(L_ERROR,"[THREAD %u] Error occured in send() function %s", dap_cur->tn, strerror(errno) ); - dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - break; + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + dap_cur->pevent.events = EPOLLOUT | EPOLLERR; + if( epoll_ctl(dap_cur->efd, EPOLL_CTL_MOD, dap_cur->socket, &dap_cur->pevent) != 0 ) { + log_it( L_ERROR, "epoll_ctl failed..." ); + dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; + break; + } + } else { + log_it(L_ERROR,"[THREAD %u] Error occured in send() function %s", dap_cur->tn, strerror(errno) ); + dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; + break; + } } total_sent += (size_t)bytes_sent; @@ -684,9 +693,7 @@ void *thread_loop( void *arg ) log_it( L_ERROR,"Socket error: %u, remove it" , dap_cur->socket ); dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; } -#ifdef _WIN32 - set_nonblock_socket(dap_cur->socket); // pconst: for winsock2 has no appropriate MSG attributes -#endif + set_nonblock_socket(dap_cur->socket); if ( !(dap_cur->flags & DAP_SOCK_SIGNAL_CLOSE) || dap_cur->no_close ) read_write_cb( dap_cur, events[i].events ); diff --git a/dap-sdk/net/server/enc_server/dap_enc_http.c b/dap-sdk/net/server/enc_server/dap_enc_http.c index e5513c121635f35a4749ae377c8983717ba23bc5..c04ddf05f18018e72f717db26160bf6e7580b79a 100644 --- a/dap-sdk/net/server/enc_server/dap_enc_http.c +++ b/dap-sdk/net/server/enc_server/dap_enc_http.c @@ -37,6 +37,7 @@ #include "dap_common.h" +#include "dap_sign.h" #include "include/dap_http.h" #include "dap_http_client.h" @@ -55,6 +56,8 @@ #define LOG_TAG "dap_enc_http" +static dap_enc_acl_callback_t s_acl_callback = NULL; + int enc_http_init() { return 0; @@ -79,6 +82,12 @@ static void _enc_http_write_reply(struct dap_http_simple *cl_st, } void dap_enc_http_json_response_format_enable(bool); + +void dap_enc_http_set_acl_callback(dap_enc_acl_callback_t a_callback) +{ + s_acl_callback = a_callback; +} + /** * @brief enc_http_proc Enc http interface * @param cl_st HTTP Simple client instance @@ -93,16 +102,29 @@ void enc_http_proc(struct dap_http_simple *cl_st, void * arg) uint8_t alice_msg[cl_st->request_size]; size_t decode_len = dap_enc_base64_decode(cl_st->request, cl_st->request_size, alice_msg, DAP_ENC_DATA_TYPE_B64); - if(decode_len != MSRLN_PKA_BYTES) { + dap_chain_hash_fast_t l_sign_hash = {}; + if (decode_len < MSRLN_PKA_BYTES) { log_it(L_WARNING, "Wrong http_enc request. Key not equal MSRLN_PKA_BYTES"); *return_code = Http_Status_BadRequest; return; + } else if (decode_len > MSRLN_PKA_BYTES) { + dap_sign_t *l_sign = (dap_sign_t *)&alice_msg[MSRLN_PKA_BYTES]; + if (dap_sign_verify(l_sign, alice_msg, MSRLN_PKA_BYTES) != 1) { + *return_code = Http_Status_Unauthorized; + return; + } + dap_sign_get_pkey_hash(l_sign, &l_sign_hash); } dap_enc_key_t* msrln_key = dap_enc_key_new(DAP_ENC_KEY_TYPE_MSRLN); msrln_key->gen_bob_shared_key(msrln_key, alice_msg, MSRLN_PKA_BYTES, (void**)&msrln_key->pub_key_data); dap_enc_ks_key_t * key_ks = dap_enc_ks_new(); + if (s_acl_callback) { + key_ks->acl_list = s_acl_callback(&l_sign_hash); + } else { + log_it(L_WARNING, "Callback for ACL is not set, pass anauthorized"); + } char encrypt_msg[DAP_ENC_BASE64_ENCODE_SIZE(msrln_key->pub_key_data_size) + 1]; size_t encrypt_msg_size = dap_enc_base64_encode(msrln_key->pub_key_data, msrln_key->pub_key_data_size, encrypt_msg, DAP_ENC_DATA_TYPE_B64); @@ -124,6 +146,7 @@ void enc_http_proc(struct dap_http_simple *cl_st, void * arg) dap_enc_key_delete(msrln_key); *return_code = Http_Status_OK; + } else{ log_it(L_ERROR,"Wrong path '%s' in the request to enc_http module",cl_st->http->url_path); *return_code = Http_Status_NotFound; diff --git a/dap-sdk/net/server/enc_server/include/dap_enc_http.h b/dap-sdk/net/server/enc_server/include/dap_enc_http.h index b92032188d2fa2f0c729f35a290182e1f442a3d1..4660b5250969586abea87ba461115e6169929bbc 100644 --- a/dap-sdk/net/server/enc_server/include/dap_enc_http.h +++ b/dap-sdk/net/server/enc_server/include/dap_enc_http.h @@ -22,6 +22,7 @@ #define _ENC_HTTP_H_ #include <stddef.h> #include <stdbool.h> +#include "dap_hash.h" struct dap_http; struct dap_http_client; @@ -63,6 +64,7 @@ typedef struct enc_http_delegate{ } enc_http_delegate_t; typedef void (*dap_enc_http_callback_t) (enc_http_delegate_t *,void *); // Callback for specific client operations +typedef uint8_t *(* dap_enc_acl_callback_t) (dap_chain_hash_fast_t *); // Callback for access list for private chain networks int enc_http_init(void); void enc_http_deinit(void); @@ -70,6 +72,7 @@ void enc_http_deinit(void); size_t enc_http_reply(enc_http_delegate_t * dg, void * data, size_t data_size); size_t enc_http_reply_f(enc_http_delegate_t * dg, const char * data, ...); +void dap_enc_http_set_acl_callback(dap_enc_acl_callback_t a_callback); enc_http_delegate_t *enc_http_request_decode(struct dap_http_simple *a_http_simple); diff --git a/dap-sdk/net/server/enc_server/include/dap_enc_ks.h b/dap-sdk/net/server/enc_server/include/dap_enc_ks.h index 828ac4e583a59a4fec184383cb655d5d3a6af19d..07c51b19ecf378acd9e7e776228aa7b89dbc4fe3 100644 --- a/dap-sdk/net/server/enc_server/include/dap_enc_ks.h +++ b/dap-sdk/net/server/enc_server/include/dap_enc_ks.h @@ -25,6 +25,7 @@ #include "uthash.h" #include "dap_enc_key.h" #include "stdbool.h" +#include "dap_hash.h" #define DAP_ENC_KS_KEY_ID_SIZE 33 struct dap_http_client; @@ -34,6 +35,7 @@ typedef struct dap_enc_ks_key{ dap_enc_key_t *key; time_t time_created; pthread_mutex_t mutex; + uint8_t *acl_list; UT_hash_handle hh; // makes this structure hashable with UTHASH library } dap_enc_ks_key_t; diff --git a/dap-sdk/net/server/http_server/dap_http_simple.c b/dap-sdk/net/server/http_server/dap_http_simple.c index 12345d2c3caa2a368288c5e482f397f31a9d4f5d..b8beddd0981899b1c3e943d9ac55d9ef681a22a5 100644 --- a/dap-sdk/net/server/http_server/dap_http_simple.c +++ b/dap-sdk/net/server/http_server/dap_http_simple.c @@ -412,10 +412,17 @@ static void s_headers_read( dap_http_client_t *a_http_client, void *a_arg ) DAP_HTTP_SIMPLE(a_http_client)->reply_byte = DAP_NEW_Z_SIZE(uint8_t, DAP_HTTP_SIMPLE(a_http_client)->reply_size_max ); if( a_http_client->in_content_length ) { - if( a_http_client->in_content_length < DAP_HTTP_SIMPLE_REQUEST_MAX ) - DAP_HTTP_SIMPLE(a_http_client)->request = calloc( 1, a_http_client->in_content_length + 1 ); + // dbg if( a_http_client->in_content_length < 3){ + if( a_http_client->in_content_length > 0){ + DAP_HTTP_SIMPLE(a_http_client)->request_size_max = a_http_client->in_content_length + 1; + DAP_HTTP_SIMPLE(a_http_client)->request = DAP_NEW_Z_SIZE(void, DAP_HTTP_SIMPLE(a_http_client)->request_size_max); + if(!DAP_HTTP_SIMPLE(a_http_client)->request){ + DAP_HTTP_SIMPLE(a_http_client)->request_size_max = 0; + log_it(L_ERROR, "Too big content-length %u in request", a_http_client->in_content_length); + } + } else - log_it( L_ERROR, "Too big content-length %u in request", a_http_client->in_content_length ); + log_it(L_ERROR, "Not defined content-length %u in request", a_http_client->in_content_length); } else { log_it( L_DEBUG, "No data section, execution proc callback" ); queue_http_request_put( DAP_HTTP_SIMPLE(a_http_client) ); @@ -435,8 +442,17 @@ void s_data_read( dap_http_client_t *a_http_client, void * a_arg ) a_http_client->client->buf_in_size : ( a_http_client->in_content_length - l_http_simple->request_size ); if( bytes_to_read ) { - memcpy( l_http_simple->request_byte + l_http_simple->request_size, a_http_client->client->buf_in, bytes_to_read ); - l_http_simple->request_size += bytes_to_read; + // Oops! The client sent more data than write in the CONTENT_LENGTH header + if(l_http_simple->request_size + bytes_to_read > l_http_simple->request_size_max){ + log_it(L_WARNING, "Oops! Client sent more data length=%u than in content-length=%u in request", l_http_simple->request_size + bytes_to_read, a_http_client->in_content_length); + l_http_simple->request_size_max = l_http_simple->request_size + bytes_to_read + 1; + // increase input buffer + l_http_simple->request = DAP_REALLOC(l_http_simple->request, l_http_simple->request_size_max); + } + if(l_http_simple->request){// request_byte=request + memcpy( l_http_simple->request_byte + l_http_simple->request_size, a_http_client->client->buf_in, bytes_to_read ); + l_http_simple->request_size += bytes_to_read; + } } if( l_http_simple->request_size >= a_http_client->in_content_length ) { diff --git a/dap-sdk/net/server/http_server/include/dap_http_simple.h b/dap-sdk/net/server/http_server/include/dap_http_simple.h index 12e3d3461e3c71eed797b6f7f2d62580670806c5..0dda2401f49d982c7528307fce9d706dc802f822 100644 --- a/dap-sdk/net/server/http_server/include/dap_http_simple.h +++ b/dap-sdk/net/server/http_server/include/dap_http_simple.h @@ -28,7 +28,7 @@ See more details here <http://www.gnu.org/licenses/>. #include "dap_http.h" //#define DAP_HTTP_SIMPLE_REQUEST_MAX 100000 - +// number of simultaneous http requests #define DAP_HTTP_SIMPLE_REQUEST_MAX 65536 struct dap_http_simple; @@ -51,6 +51,7 @@ typedef struct dap_http_simple { }; size_t request_size; + size_t request_size_max; size_t reply_size; size_t reply_size_max; size_t reply_sent; diff --git a/dap-sdk/net/stream/ch/dap_stream_ch.c b/dap-sdk/net/stream/ch/dap_stream_ch.c index 6402394bf3fb0db0276b505c77212692d9cac02b..6ce73a49d4b1c22712b4c572e66f7717d08d0c66 100644 --- a/dap-sdk/net/stream/ch/dap_stream_ch.c +++ b/dap-sdk/net/stream/ch/dap_stream_ch.c @@ -45,6 +45,13 @@ #define LOG_TAG "dap_stream_ch" +static struct dap_stream_ch_table_t { + dap_stream_ch_t *ch; + UT_hash_handle hh; +} *s_ch_table = NULL; + +static pthread_mutex_t s_ch_table_lock; + /** * @brief stream_ch_init Init stream channel module * @return Zero if ok others if no @@ -59,6 +66,7 @@ int dap_stream_ch_init() log_it(L_CRITICAL,"Can't init stream channel packet submodule"); return -1; } + pthread_mutex_init(&s_ch_table_lock, NULL); log_it(L_NOTICE,"Module stream channel initialized"); return 0; } @@ -68,6 +76,7 @@ int dap_stream_ch_init() */ void dap_stream_ch_deinit() { + pthread_mutex_destroy(&s_ch_table_lock); } /** @@ -82,7 +91,8 @@ dap_stream_ch_t* dap_stream_ch_new(dap_stream_t* a_stream, uint8_t id) dap_stream_ch_t* ret = DAP_NEW_Z(dap_stream_ch_t); ret->stream = a_stream; ret->proc = proc; - ret->ready_to_read=true; + ret->ready_to_read = true; + pthread_mutex_init(&(ret->mutex),NULL); if(ret->proc->new_callback) ret->proc->new_callback(ret,NULL); @@ -92,6 +102,11 @@ dap_stream_ch_t* dap_stream_ch_new(dap_stream_t* a_stream, uint8_t id) a_stream->channel_count++; pthread_rwlock_unlock(&a_stream->rwlock); + struct dap_stream_ch_table_t *l_new_ch = DAP_NEW_Z(struct dap_stream_ch_table_t); + pthread_mutex_lock(&s_ch_table_lock); + HASH_ADD_PTR(s_ch_table, ch, l_new_ch); + pthread_mutex_unlock(&s_ch_table_lock); + return ret; }else{ log_it(L_WARNING, "Unknown stream processor with id %uc",id); @@ -99,24 +114,42 @@ dap_stream_ch_t* dap_stream_ch_new(dap_stream_t* a_stream, uint8_t id) } } +bool dap_stream_ch_valid(dap_stream_ch_t *a_ch) +{ + struct dap_stream_ch_table_t *l_ret; + if(!a_ch) + return false; + pthread_mutex_lock(&s_ch_table_lock); + HASH_FIND_PTR(s_ch_table, a_ch, l_ret); + pthread_mutex_unlock(&s_ch_table_lock); + return l_ret; +} + /** * @brief stream_ch_delete Delete channel instance * @param ch Channel delete */ -void dap_stream_ch_delete(dap_stream_ch_t*ch) +void dap_stream_ch_delete(dap_stream_ch_t *a_ch) { - if(ch->proc) - if(ch->proc->delete_callback) - ch->proc->delete_callback(ch,NULL); + pthread_mutex_lock(&s_ch_table_lock); + struct dap_stream_ch_table_t *l_ret;; + HASH_FIND_PTR(s_ch_table, a_ch, l_ret); + HASH_DEL(s_ch_table, l_ret); + pthread_mutex_unlock(&s_ch_table_lock); - pthread_mutex_destroy(&(ch->mutex)); + pthread_mutex_lock(&a_ch->mutex); + if (a_ch->proc) + if (a_ch->proc->delete_callback) + a_ch->proc->delete_callback(a_ch, NULL); + pthread_mutex_unlock(&a_ch->mutex); + pthread_mutex_destroy(&a_ch->mutex); /* fixed raise, but probably may be memory leak! if(ch->internal){ free(ch->internal); } */ - //free(ch); + DAP_DELETE(a_ch); } /** @@ -126,6 +159,9 @@ void dap_stream_ch_delete(dap_stream_ch_t*ch) */ void dap_stream_ch_set_ready_to_read(dap_stream_ch_t * a_ch,bool a_is_ready) { + if (!dap_stream_ch_valid(a_ch)) { + return; + } pthread_mutex_lock(&a_ch->mutex); if( a_ch->ready_to_read != a_is_ready){ //log_it(L_DEBUG,"Change channel '%c' to %s", (char) ch->proc->id, is_ready?"true":"false"); @@ -149,6 +185,9 @@ void dap_stream_ch_set_ready_to_read(dap_stream_ch_t * a_ch,bool a_is_ready) */ void dap_stream_ch_set_ready_to_write(dap_stream_ch_t * ch,bool is_ready) { + if (!dap_stream_ch_valid(ch)) { + return; + } pthread_mutex_lock(&ch->mutex); if(ch->ready_to_write!=is_ready){ //log_it(L_DEBUG,"Change channel '%c' to %s", (char) ch->proc->id, is_ready?"true":"false"); @@ -166,3 +205,37 @@ void dap_stream_ch_set_ready_to_write(dap_stream_ch_t * ch,bool is_ready) } pthread_mutex_unlock(&ch->mutex); } + +/** + * @brief dap_stream_ch_get_ready_to_read + * @param a_ch + * @return + */ +bool dap_stream_ch_get_ready_to_read(dap_stream_ch_t * a_ch) +{ + if (!dap_stream_ch_valid(a_ch)) { + return false; + } + bool l_ret; + pthread_mutex_lock(&a_ch->mutex); + l_ret = a_ch->ready_to_read; + pthread_mutex_unlock(&a_ch->mutex); + return l_ret; +} + +/** + * @brief dap_stream_ch_get_ready_to_write + * @param a_ch + * @return + */ +bool dap_stream_ch_get_ready_to_write(dap_stream_ch_t * a_ch) +{ + if (!dap_stream_ch_valid(a_ch)) { + return false; + } + bool l_ret; + pthread_mutex_lock(&a_ch->mutex); + l_ret = a_ch->ready_to_write; + pthread_mutex_unlock(&a_ch->mutex); + return l_ret; +} diff --git a/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c b/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c index cb575948c43b1c9604965ca8ec56f881f7cc5bbc..b1600592b17f4572c400430a2aba24b0fb123f24 100644 --- a/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c +++ b/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c @@ -79,6 +79,9 @@ size_t dap_stream_ch_pkt_write(struct dap_stream_ch * a_ch, uint8_t a_type, con log_it(L_WARNING,"Zero data size to write out in channel"); return 0; } + if (!dap_stream_ch_valid(a_ch)) { + return 0; + } pthread_mutex_lock( &a_ch->mutex); //log_it(L_DEBUG,"Output: Has %u bytes of %c type for %c channel id",data_size, (char)type, (char) ch->proc->id ); diff --git a/dap-sdk/net/stream/ch/include/dap_stream_ch.h b/dap-sdk/net/stream/ch/include/dap_stream_ch.h index cde7633792a8928bb6398c0dc67def14e3bb1f00..a9c1f484fee1a16f231be3a3ea13a1d046f5a834 100644 --- a/dap-sdk/net/stream/ch/include/dap_stream_ch.h +++ b/dap-sdk/net/stream/ch/include/dap_stream_ch.h @@ -58,34 +58,11 @@ dap_stream_ch_t* dap_stream_ch_new( dap_stream_t * dap_stream,uint8_t id); void dap_stream_ch_set_ready_to_read(dap_stream_ch_t * ch,bool is_ready); void dap_stream_ch_set_ready_to_write(dap_stream_ch_t * ch,bool is_ready); -/** - * @brief dap_stream_ch_get_ready_to_read - * @param a_ch - * @return - */ -static inline bool dap_stream_ch_get_ready_to_read(dap_stream_ch_t * a_ch) -{ - bool l_ret; - pthread_mutex_lock(&a_ch->mutex); - l_ret = a_ch->ready_to_read; - pthread_mutex_unlock(&a_ch->mutex); - return l_ret; -} - -/** - * @brief dap_stream_ch_get_ready_to_write - * @param a_ch - * @return - */ -static inline bool dap_stream_ch_get_ready_to_write(dap_stream_ch_t * a_ch) -{ - bool l_ret; - pthread_mutex_lock(&a_ch->mutex); - l_ret = a_ch->ready_to_write; - pthread_mutex_unlock(&a_ch->mutex); - return l_ret; -} - -void dap_stream_ch_delete(dap_stream_ch_t*ch); +bool dap_stream_ch_get_ready_to_read(dap_stream_ch_t *a_ch); +bool dap_stream_ch_get_ready_to_write(dap_stream_ch_t *a_ch); + +void dap_stream_ch_delete(dap_stream_ch_t *a_ch); + +bool dap_stream_ch_valid(dap_stream_ch_t *a_ch); #endif diff --git a/dap-sdk/net/stream/session/include/dap_stream_session.h b/dap-sdk/net/stream/session/include/dap_stream_session.h index 9fdfb91c061fbd4c62356f17eb39cc83863ed7e7..2f8d9e624d23a5eebb694515b06796f31aac87f7 100644 --- a/dap-sdk/net/stream/session/include/dap_stream_session.h +++ b/dap-sdk/net/stream/session/include/dap_stream_session.h @@ -30,6 +30,7 @@ #include "uthash.h" #include "dap_enc_key.h" +#include "dap_hash.h" typedef enum stream_session_type {STREAM_SESSION_TYPE_MEDIA=0,STREAM_SESSION_TYPE_VPN} stream_session_type_t; typedef enum stream_session_connection_type {STEAM_SESSION_HTTP = 0, STREAM_SESSION_UDP, STREAM_SESSION_END_TYPE} stream_session_connection_type_t; @@ -56,6 +57,7 @@ struct dap_stream_session { stream_session_connection_type_t conn_type; stream_session_type_t type; + uint8_t *acl; UT_hash_handle hh; struct in_addr tun_client_addr; diff --git a/dap-sdk/net/stream/stream/dap_stream_ctl.c b/dap-sdk/net/stream/stream/dap_stream_ctl.c index 80a9427af0390ce774fbe849e93f6706f4399b56..21bd39eb99423262c6199bc573df54b2b48036e8 100644 --- a/dap-sdk/net/stream/stream/dap_stream_ctl.c +++ b/dap-sdk/net/stream/stream/dap_stream_ctl.c @@ -50,6 +50,7 @@ #include "dap_stream_session.h" #include "dap_stream_ctl.h" #include "http_status_code.h" +#include "dap_enc_ks.h" #define LOG_TAG "dap_stream_ctl" @@ -145,6 +146,16 @@ void s_proc(struct dap_http_simple *a_http_simple, void * a_arg) dap_random_string_fill(key_str, KEX_KEY_STR_SIZE); ss->key = dap_enc_key_new_generate( s_socket_forward_key.type, key_str, KEX_KEY_STR_SIZE, NULL, 0, s_socket_forward_key.size); + dap_http_header_t *l_hdr_key_id = dap_http_header_find(a_http_simple->http->in_headers, "KeyID"); + if (l_hdr_key_id) { + dap_enc_ks_key_t *l_ks_key = dap_enc_ks_find(l_hdr_key_id->value); + if (!l_ks_key) { + log_it(L_WARNING, "Key with ID %s not found", l_hdr_key_id->value); + *return_code = Http_Status_BadRequest; + return; + } + ss->acl = l_ks_key->acl_list; + } enc_http_reply_f(l_dg,"%u %s",ss->id,key_str); *return_code = Http_Status_OK; @@ -154,6 +165,7 @@ void s_proc(struct dap_http_simple *a_http_simple, void * a_arg) }else{ log_it(L_ERROR,"Wrong request: \"%s\"",l_dg->in_query); *return_code = Http_Status_BadRequest; + return; } unsigned int conn_t = 0; diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 96694458347514411f164876956119eb02eeb6a0..ed25e99e7a4e96db0417ecefa426eb8c4e18ae85 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -49,6 +49,12 @@ typedef struct dap_chain_atom_iter{ void * _inheritor; } dap_chain_atom_iter_t; +typedef enum dap_chain_atom_verify_res{ + ATOM_ACCEPT, + ATOM_PASS, + ATOM_REJECT, + ATOM_MOVE_TO_THRESHOLD +} dap_chain_atom_verify_res_t; typedef dap_chain_t* (*dap_chain_callback_new_t)(void); @@ -56,7 +62,8 @@ typedef void (*dap_chain_callback_t)(dap_chain_t *); typedef int (*dap_chain_callback_new_cfg_t)(dap_chain_t*, dap_config_t *); typedef void (*dap_chain_callback_ptr_t)(dap_chain_t *, void * ); -typedef int (*dap_chain_callback_atom_t)(dap_chain_t *, dap_chain_atom_ptr_t ); +typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_t)(dap_chain_t *, dap_chain_atom_ptr_t ); +typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_verify_t)(dap_chain_t *, dap_chain_atom_ptr_t ); typedef int (*dap_chain_callback_atom_size_t)(dap_chain_t *, dap_chain_atom_ptr_t ,size_t); typedef size_t (*dap_chain_callback_atom_get_hdr_size_t)(void); typedef size_t (*dap_chain_callback_atom_hdr_get_size_t)(dap_chain_atom_ptr_t ); @@ -112,7 +119,7 @@ typedef struct dap_chain{ dap_chain_callback_t callback_delete; dap_chain_callback_atom_t callback_atom_add; - dap_chain_callback_atom_t callback_atom_verify; + dap_chain_callback_atom_verify_t callback_atom_verify; dap_chain_datum_callback_datum_pool_proc_add_t callback_datums_pool_proc; dap_chain_datum_callback_datum_pool_proc_add_with_group_t callback_datums_pool_proc_with_group; diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c index 22d437782c12cd4189d5b922ef8503aa5c509f0e..74dcd903c674c4f4e93b15f8ca5c9da53562adbc 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c @@ -43,6 +43,7 @@ #include "dap_common.h" #include "dap_strfuncs.h" +#include "dap_cert.h" #include "uthash.h" #include "dap_http_client.h" #include "dap_chain_global_db.h" @@ -192,8 +193,27 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) pthread_mutex_lock(&l_ch_chain_net->mutex); dap_stream_ch_pkt_t *l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; dap_stream_ch_chain_net_pkt_t *l_ch_chain_net_pkt = (dap_stream_ch_chain_net_pkt_t *) l_ch_pkt->data; - size_t l_ch_chain_net_pkt_data_size = (size_t) l_ch_pkt->hdr.size - sizeof (l_ch_chain_net_pkt->hdr); - if(l_ch_chain_net_pkt) { + uint8_t l_acl_idx = dap_chain_net_acl_idx_by_id(l_ch_chain_net_pkt->hdr.net_id); + bool l_error = false; + char l_err_str[64]; + if (l_acl_idx == (uint8_t)-1) { + log_it(L_ERROR, "Invalid net id in packet"); + strcpy(l_err_str, "ERROR_NET_INVALID_ID"); + l_error = true; + } + if (!l_error && a_ch->stream->session->acl && !a_ch->stream->session->acl[l_acl_idx]) { + log_it(L_WARNING, "Unauthorized request attempt to network %s", + dap_chain_net_by_id(l_ch_chain_net_pkt->hdr.net_id)->pub.name); + strcpy(l_err_str, "ERROR_NET_NOT_AUTHORIZED"); + l_error = true; + } + if (l_error) { + dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , + l_ch_chain_net_pkt->hdr.net_id, l_err_str, strlen(l_err_str) + 1); + dap_stream_ch_set_ready_to_write(a_ch, true); + } + //size_t l_ch_chain_net_pkt_data_size = (size_t) l_ch_pkt->hdr.size - sizeof (l_ch_chain_net_pkt->hdr); + if (!l_error && l_ch_chain_net_pkt) { size_t l_ch_chain_net_pkt_data_size = l_ch_pkt->hdr.size - sizeof(dap_stream_ch_chain_net_pkt_hdr_t); switch (l_ch_pkt->hdr.type) { case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_DBG: { @@ -239,7 +259,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str,sizeof (l_err_str)); dap_stream_ch_set_ready_to_write(a_ch, true); - log_it(L_WARNING,"Invalid net id in packet"); + log_it(L_ERROR, "Invalid net id in packet"); } else { if (dap_db_set_cur_node_addr_exp( l_addr->uint64, l_net->pub.name )) log_it(L_NOTICE,"Set up cur node address 0x%016llX",l_addr->uint64); @@ -284,7 +304,6 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } } break; - } if(l_ch_chain_net->notify_callback) l_ch_chain_net->notify_callback(l_ch_chain_net,l_ch_pkt->hdr.type, l_ch_chain_net_pkt, diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 7f93f8111a2ece71cf4d45ca96c086a3f1399d6a..92bd61bb91ee01e28937779ac9abf2ddb295668f 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -130,8 +130,27 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) if(l_ch_chain) { dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; dap_stream_ch_chain_pkt_t * l_chain_pkt = (dap_stream_ch_chain_pkt_t *) l_ch_pkt->data; + uint8_t l_acl_idx = dap_chain_net_acl_idx_by_id(l_chain_pkt->hdr.net_id); + bool l_error = false; + char l_err_str[64]; + if (l_acl_idx == (uint8_t)-1) { + log_it(L_ERROR, "Invalid net id in packet"); + strcpy(l_err_str, "ERROR_NET_INVALID_ID"); + l_error = true; + } + if (!l_error && a_ch->stream->session->acl && !a_ch->stream->session->acl[l_acl_idx]) { + log_it(L_WARNING, "Unauthorized request attempt to network %s", + dap_chain_net_by_id(l_chain_pkt->hdr.net_id)->pub.name); + strcpy(l_err_str, "ERROR_NET_NOT_AUTHORIZED"); + l_error = true; + } + if (l_error) { + dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, l_err_str); + dap_stream_ch_set_ready_to_write(a_ch, true); + } size_t l_chain_pkt_data_size = l_ch_pkt->hdr.size - sizeof(l_chain_pkt->hdr); - if(l_chain_pkt) { + if (!l_error && l_chain_pkt) { switch (l_ch_pkt->hdr.type) { case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_ALL: { log_it(L_INFO, "In: SYNCED_ALL pkt"); @@ -336,8 +355,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) if(l_chain_pkt_data_size > 0) { dap_chain_atom_ptr_t l_atom_copy = DAP_CALLOC(1, l_chain_pkt_data_size); memcpy(l_atom_copy, l_chain_pkt->data, l_chain_pkt_data_size); - if(l_chain->callback_atom_add(l_chain, l_atom_copy) == 0 && - dap_chain_has_file_store(l_chain)) { + dap_chain_atom_verify_res_t l_atom_add_res = l_chain->callback_atom_add(l_chain, l_atom_copy); + if(l_atom_add_res == ATOM_ACCEPT && dap_chain_has_file_store(l_chain)) { // append to file dap_chain_cell_id_t l_cell_id; l_cell_id.uint64 = l_chain_pkt->hdr.cell_id.uint64; @@ -353,6 +372,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) // delete cell and close file dap_chain_cell_delete(l_cell); } + if(l_atom_add_res == ATOM_PASS) + DAP_DELETE(l_atom_copy); } else { log_it(L_WARNING, "Empty chain packet"); dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, diff --git a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c index a9bc51329619874adb7c770098624a7646ed7a93..44be5c56f1fe14ee13efcf88f766a14fbe4d1a48 100644 --- a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c +++ b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c @@ -273,7 +273,7 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ } if (! l_is_enough_balance ){ char *l_addr_str = dap_chain_addr_to_str(&l_addr); - log_it(L_WARNING, "Verify of event is false, because bal=0 for addr=%s", l_addr_str); + log_it(L_WARNING, "Verify of event is false, because bal is not enough for addr=%s", l_addr_str); DAP_DELETE(l_addr_str); return 0; //-1; } diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c index 5626597d1e2fb19c3a85424fb4179f448dd6ada8..59af3853fdb8f111e211d8e975e235949373d166 100644 --- a/modules/consensus/none/dap_chain_cs_none.c +++ b/modules/consensus/none/dap_chain_cs_none.c @@ -68,8 +68,8 @@ typedef struct dap_chain_gdb_private static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net); // Atomic element organization callbacks -static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t); // Accept new event in gdb -static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t); // Verify new event in gdb +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t); // Accept new event in gdb +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t); // Verify new event in gdb static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t); // Get gdb event size static size_t s_chain_callback_atom_get_static_hdr_size(void); // Get gdb event header size @@ -322,7 +322,7 @@ static size_t s_chain_callback_datums_pool_proc_with_group(dap_chain_t * a_chain * @param a_datums * @param a_datums_size */ -static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) { dap_chain_gdb_t * l_gdb = DAP_CHAIN_GDB(a_chain); dap_chain_gdb_private_t *l_gdb_priv = PVT(l_gdb); @@ -344,11 +344,11 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t // don't save bad transactions to base if(dap_chain_ledger_tx_add(a_chain->ledger, l_tx) != 1) - return -1; + return ATOM_REJECT; //}else // return -2; }break; - default: return -1; + default: return ATOM_REJECT; } dap_chain_gdb_datum_hash_item_t * l_hash_item = DAP_NEW_Z(dap_chain_gdb_datum_hash_item_t); @@ -361,7 +361,7 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t log_it(L_DEBUG,"Load mode, doesnt save item %s:%s", l_hash_item->key, l_gdb_priv->group_datums); DL_APPEND(l_gdb_priv->hash_items, l_hash_item); - return 0; + return ATOM_ACCEPT; } /** @@ -370,11 +370,11 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t * @param a_atom * @return */ -static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) { (void) a_chain; (void) a_atom; - return 0; + return ATOM_ACCEPT; } /** diff --git a/modules/global-db/dap_chain_global_db_driver_cdb.c b/modules/global-db/dap_chain_global_db_driver_cdb.c index 88221e95d522ec66d094e9a1011ea756c765a9ea..5adb80c769556202b7ef59097e40dbfd349b38b6 100644 --- a/modules/global-db/dap_chain_global_db_driver_cdb.c +++ b/modules/global-db/dap_chain_global_db_driver_cdb.c @@ -32,7 +32,7 @@ #include "dap_common.h" #include "dap_hash.h" -#include "dap_strfuncs.h" +#include "dap_strfuncs.h" // #include <dap_fnmatch.h> #include "dap_chain_global_db_driver_cdb.h" #include "dap_file_utils.h" @@ -471,11 +471,9 @@ dap_list_t* dap_db_driver_cdb_get_groups_by_mask(const char *a_group_mask) pthread_mutex_lock(&cdb_mutex); HASH_ITER(hh, s_cdb, cur_cdb, tmp) { - if(strstr(cur_cdb->local_group, a_group_mask)) { - if(!strstr(cur_cdb->local_group, ".del")) { + if(!dap_fnmatch(a_group_mask, cur_cdb->local_group, 0)) + if(dap_fnmatch("*.del", cur_cdb->local_group, 0)) l_ret_list = dap_list_prepend(l_ret_list, dap_strdup(cur_cdb->local_group)); - } - } } pthread_mutex_unlock(&cdb_mutex); return l_ret_list; diff --git a/modules/global-db/dap_chain_global_db_hist.c b/modules/global-db/dap_chain_global_db_hist.c index 49195daf7d666cc0f26302906a3b6ec37dd91500..c2683b156035b3ac7eab75ef6fed3f7d9cf45301 100644 --- a/modules/global-db/dap_chain_global_db_hist.c +++ b/modules/global-db/dap_chain_global_db_hist.c @@ -1130,11 +1130,13 @@ bool dap_db_history_truncate(void) */ uint64_t dap_db_log_get_group_history_last_id(const char *a_history_group_name) { + uint64_t result = 0; dap_store_obj_t *l_last_obj = dap_chain_global_db_get_last(a_history_group_name); if(l_last_obj) { - return l_last_obj->id; - }else - return 0; + result = l_last_obj->id; + dap_store_obj_free(l_last_obj, 1); + } + return result; } /** @@ -1253,7 +1255,7 @@ static void *s_list_thread_proc(void *arg) while(l_dap_db_log_list->group_cur < l_dap_db_log_list->group_number) { l_dap_db_log_list->group_cur++; // check for empty group - if(l_dap_db_log_list->group_number_items[l_dap_db_log_list->group_cur] < 1) { + if( !(l_dap_db_log_list->group_number) || (l_dap_db_log_list->group_number_items[l_dap_db_log_list->group_cur] < 1)) { continue; } break; diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index 28ce8491f0bd1248a68cef2b09d6b98480fb1624..9b4c4ebe29990324b568e1323b28a9d8ef8a9eac 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -557,7 +557,7 @@ dap_chain_hash_fast_t* dap_chain_proc_tx_create_cond(dap_chain_net_t * a_net, if(a_net->pub.default_chain) l_chain = a_net->pub.default_chain; else - dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_TX); + l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_TX); if(!l_chain) return NULL; diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt index 990616476d68e2d2a843e53ed33de33bacf1e261..9c3c877a0e8c713e8567edfa7f758ec57af7ceaf 100644 --- a/modules/net/CMakeLists.txt +++ b/modules/net/CMakeLists.txt @@ -45,7 +45,7 @@ endif() if(UNIX) target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_chain - dap_chain_crypto dap_chain_wallet dap_chain_net_srv dap_chain_net_srv_vpn dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake + dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake resolv ) endif() diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 086bb90dd2ddcd2eed231f47bfb9aa66d474901b..5a9025d903b6abd49d6bdfa932643094081b727e 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -60,6 +60,8 @@ #include "dap_config.h" #include "dap_hash.h" #include "dap_cert.h" +#include "dap_cert_file.h" +#include "dap_enc_http.h" #include "dap_chain_common.h" #include "dap_chain_net.h" #include "dap_chain_net_srv.h" @@ -141,6 +143,7 @@ typedef struct dap_chain_net_pvt{ dap_chain_net_state_t state; dap_chain_net_state_t state_target; + uint16_t acl_idx; } dap_chain_net_pvt_t; typedef struct dap_chain_net_item{ @@ -174,7 +177,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net); static void * s_net_proc_thread ( void * a_net); static void s_net_proc_thread_start( dap_chain_net_t * a_net ); static void s_net_proc_kill( dap_chain_net_t * a_net ); -int s_net_load(const char * a_net_name); +int s_net_load(const char * a_net_name, uint16_t a_acl_idx); static void s_gbd_history_callback_notify (void * a_arg,const char a_op_code, const char * a_prefix, const char * a_group, const char * a_key, const void * a_value, @@ -185,6 +188,23 @@ static int s_cli_net(int argc, char ** argv, void *arg_func, char **str_reply); static bool s_seed_mode = false; +static uint8_t *dap_chain_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash); + +char *dap_chain_net_get_gdb_group_acl(dap_chain_net_t *a_net) +{ + if (a_net) { + const char l_path[] = "network/"; + char l_cfg_path[strlen(a_net->pub.name) + strlen(l_path) + 1]; + strcpy(l_cfg_path, l_path); + strcat(l_cfg_path, a_net->pub.name); + dap_config_t *l_cfg = dap_config_open(l_cfg_path); + const char *l_auth_gdb = dap_config_get_item_str(l_cfg, "auth", "acl_accept_ca_gdb"); + if (l_auth_gdb) { + return dap_strdup_printf("%s.%s", a_net->pub.gdb_groups_prefix, l_auth_gdb); + } + } + return NULL; +} /** * @brief s_net_set_go_sync @@ -497,6 +517,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net) l_pvt_net->links_success = 0; l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC; l_pvt_net->state = NET_STATE_ONLINE; + break; } if (l_links_count < l_pvt_net->links_addrs_count) { l_pvt_net->links_count++; @@ -1013,9 +1034,15 @@ int dap_chain_net_init() "net -net <chain net name> stats tx [-from <From time>] [-to <To time>] [-prev_sec <Seconds>] \n" "\tTransactions statistics. Time format is <Year>-<Month>-<Day>_<Hours>:<Minutes>:<Seconds> or just <Seconds> \n" "net -net <chain net name> sync < all | gdb | chains >\n" - "\tSyncronyze gdb, chains or everything\n\n" + "\tSyncronyze gdb, chains or everything\n" "net -net <chain net name> link < list | add | del | info | establish >\n" - "\tList,add,del, dump or establish links\n\n" + "\tList, add, del, dump or establish links\n" + "net -net <chain net name> ca add {-cert <cert name> | -hash <cert hash>}\n" + "\tAdd certificate to list of authority cetificates in GDB group\n" + "net -net <chain net name> ca list\n" + "\tPrint list of authority cetificates from GDB group\n" + "net -net <chain net name> ca del -hash <cert hash>\n" + "\tDelete certificate from list of authority cetificates in GDB group by it's hash\n" ); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); dap_chain_global_db_add_history_group_prefix("global", GROUP_LOCAL_HISTORY); @@ -1028,6 +1055,8 @@ int dap_chain_net_init() s_required_links_count = dap_config_get_item_int32_default(g_config, "general", "require_links", s_required_links_count); dap_chain_net_load_all(); + + dap_enc_http_set_acl_callback(dap_chain_net_set_acl); return 0; } @@ -1037,6 +1066,7 @@ void dap_chain_net_load_all() DIR * l_net_dir = opendir( l_net_dir_str); if ( l_net_dir ){ struct dirent * l_dir_entry; + uint16_t l_acl_idx = 0; while ( (l_dir_entry = readdir(l_net_dir) )!= NULL ){ if (l_dir_entry->d_name[0]=='\0' || l_dir_entry->d_name[0]=='.') continue; @@ -1059,13 +1089,42 @@ void dap_chain_net_load_all() char* l_dot_pos = strchr(l_dir_entry->d_name,'.'); if ( l_dot_pos ) *l_dot_pos = '\0'; - s_net_load(l_dir_entry->d_name ); + s_net_load(l_dir_entry->d_name, l_acl_idx++); } closedir(l_net_dir); } DAP_DELETE (l_net_dir_str); } +void s_set_reply_text_node_status(char **a_str_reply, dap_chain_net_t * a_net){ + const char* l_node_address_text_block = NULL; + dap_chain_node_addr_t l_cur_node_addr = { 0 }; + l_cur_node_addr.uint64 = dap_chain_net_get_cur_addr(a_net) ? dap_chain_net_get_cur_addr(a_net)->uint64 : dap_db_get_cur_node_addr(a_net->pub.name); + if(!l_cur_node_addr.uint64) + l_node_address_text_block = dap_strdup_printf(", cur node address not defined"); + else + l_node_address_text_block = dap_strdup_printf(", cur node address " NODE_ADDR_FP_STR,NODE_ADDR_FP_ARGS_S(l_cur_node_addr)); + + const char* l_sync_current_link_text_block = NULL; + if(PVT(a_net)->state == NET_STATE_LINKS_PREPARE || + PVT(a_net)->state == NET_STATE_LINKS_CONNECTING || + PVT(a_net)->state == NET_STATE_SYNC_GDB || + PVT(a_net)->state == NET_STATE_SYNC_CHAINS) + l_sync_current_link_text_block = dap_strdup_printf(", processing link %u from %u", + PVT(a_net)->links_count, PVT(a_net)->links_addrs_count); + + dap_chain_node_cli_set_reply_text(a_str_reply, + "Network \"%s\" has state %s (target state %s)%s%s", + a_net->pub.name, c_net_states[PVT(a_net)->state], + c_net_states[PVT(a_net)->state_target], + (l_sync_current_link_text_block)? l_sync_current_link_text_block: "", + l_node_address_text_block + ); + + DAP_DELETE(l_sync_current_link_text_block); + DAP_DELETE(l_node_address_text_block); +} + /** * @brief s_cli_net * @param argc @@ -1076,6 +1135,7 @@ void dap_chain_net_load_all() */ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) { + UNUSED(arg_func); int arg_index = 1; dap_chain_net_t * l_net = NULL; @@ -1111,11 +1171,13 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) const char *l_go_str = NULL; const char *l_get_str = NULL; const char *l_stats_str = NULL; + const char *l_ca_str = NULL; dap_chain_node_cli_find_option_val(argv, arg_index, argc, "sync", &l_sync_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "link", &l_links_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "go", &l_go_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "get", &l_get_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "stats", &l_stats_str); + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ca", &l_ca_str); if ( l_stats_str ){ if ( strcmp(l_stats_str,"tx") == 0 ) { @@ -1204,26 +1266,7 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) } else if ( l_get_str){ if ( strcmp(l_get_str,"status") == 0 ) { - // get current node address - dap_chain_node_addr_t l_cur_node_addr = { 0 }; - l_cur_node_addr.uint64 = dap_chain_net_get_cur_addr(l_net) ? dap_chain_net_get_cur_addr(l_net)->uint64 : dap_db_get_cur_node_addr(l_net->pub.name); - if(!l_cur_node_addr.uint64) { - dap_chain_node_cli_set_reply_text(a_str_reply, - "Network \"%s\" has state %s (target state %s), active links %u from %u, cur node address not defined", - l_net->pub.name, c_net_states[PVT(l_net)->state], - c_net_states[PVT(l_net)->state_target], PVT(l_net)->links_count, - PVT(l_net)->links_addrs_count - ); - } - else { - dap_chain_node_cli_set_reply_text(a_str_reply, - "Network \"%s\" has state %s (target state %s), active links %u from %u, cur node address " NODE_ADDR_FP_STR, - l_net->pub.name, c_net_states[PVT(l_net)->state], - c_net_states[PVT(l_net)->state_target], PVT(l_net)->links_count, - PVT(l_net)->links_addrs_count, - NODE_ADDR_FP_ARGS_S(l_cur_node_addr) - ); - } + s_set_reply_text_node_status(a_str_reply, l_net); ret = 0; } } else if ( l_links_str ){ @@ -1267,6 +1310,91 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) "Subcommand \"sync\" requires one of parameter: all,gdb,chains\n"); ret = -2; } + } else if (l_ca_str) { + if (strcmp(l_ca_str, "add") == 0 ) { + const char *l_cert_string = NULL, *l_hash_string = NULL; + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-cert", &l_cert_string); + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-hash", &l_hash_string); + if (!l_cert_string && !l_hash_string) { + dap_chain_node_cli_set_reply_text(a_str_reply, "One of -cert or -hash parameters is mandatory"); + return -6; + } + if (l_cert_string) { + dap_cert_t * l_cert = dap_cert_find_by_name(l_cert_string); + if (l_cert == NULL) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find \"%s\" certificate", l_cert_string); + return -7; + } + if (l_cert->enc_key == NULL) { + dap_chain_node_cli_set_reply_text(a_str_reply, "No key found in \"%s\" certificate", l_cert_string ); + return -8; + } + // Get publivc key hash + size_t l_pub_key_size = 0; + uint8_t *l_pub_key = dap_enc_key_serealize_pub_key(l_cert->enc_key, &l_pub_key_size);; + if (l_pub_key == NULL) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't serialize public key of certificate \"%s\"", l_cert_string); + return -9; + } + dap_chain_hash_fast_t l_pkey_hash; + dap_hash_fast(l_pub_key, l_pub_key_size, &l_pkey_hash); + l_hash_string = dap_chain_hash_fast_to_str_new(&l_pkey_hash); + } + const char c = '1'; + char *l_gdb_group_str = dap_chain_net_get_gdb_group_acl(l_net); + if (!l_gdb_group_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Database ACL group not defined for this network"); + return -11; + } + ret = dap_chain_global_db_gr_set(dap_strdup(l_hash_string), (void *)&c, 1, dap_chain_net_get_gdb_group_acl(l_net)); + DAP_DELETE(l_gdb_group_str); + if (!ret) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't save public key hash in database"); + return -10; + } + return 0; + } else if (strcmp(l_ca_str, "list") == 0 ) { + char *l_gdb_group_str = dap_chain_net_get_gdb_group_acl(l_net); + if (!l_gdb_group_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Database ACL group not defined for this network"); + return -11; + } + size_t l_objs_count; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_gdb_group_str, &l_objs_count); + DAP_DELETE(l_gdb_group_str); + dap_string_t *l_reply = dap_string_new(""); + for (size_t i = 0; i < l_objs_count; i++) { + dap_string_append(l_reply, l_objs[i].key); + dap_string_append(l_reply, "\n"); + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + *a_str_reply = l_reply->len ? l_reply->str : dap_strdup("No entries found"); + dap_string_free(l_reply, false); + return 0; + } else if (strcmp(l_ca_str, "del") == 0 ) { + const char *l_hash_string = NULL; + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-hash", &l_hash_string); + if (!l_hash_string) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Format should be 'net ca del -hash <hash string>"); + return -6; + } + char *l_gdb_group_str = dap_chain_net_get_gdb_group_acl(l_net); + if (!l_gdb_group_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Database ACL group not defined for this network"); + return -11; + } + ret = dap_chain_global_db_gr_del((char *)l_hash_string, l_gdb_group_str); + DAP_DELETE(l_gdb_group_str); + if (!ret) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Cant't find certificate public key hash in database"); + return -10; + } + return 0; + } else { + dap_chain_node_cli_set_reply_text(a_str_reply, + "Subcommand \"ca\" requires one of parameter: add, list, del\n"); + ret = -5; + } } else { dap_chain_node_cli_set_reply_text(a_str_reply,"Command requires one of subcomand: sync, links\n"); ret = -1; @@ -1298,7 +1426,7 @@ static int callback_compare_prioritity_list(const void * a_item1, const void * a * @param a_net_name * @return */ -int s_net_load(const char * a_net_name) +int s_net_load(const char * a_net_name, uint16_t a_acl_idx) { dap_config_t *l_cfg=NULL; dap_string_t *l_cfg_path = dap_string_new("network/"); @@ -1320,6 +1448,7 @@ int s_net_load(const char * a_net_name) return -1; } PVT(l_net)->load_mode = true; + PVT(l_net)->acl_idx = a_acl_idx; l_net->pub.gdb_groups_prefix = dap_strdup ( dap_config_get_item_str_default(l_cfg , "general" , "gdb_groups_prefix", dap_config_get_item_str(l_cfg , "general" , "name" ) ) ); @@ -1351,7 +1480,7 @@ int s_net_load(const char * a_net_name) while(l_groups) { char *l_group_name = l_groups->data; // do not use groups with names like *.del - if(!strstr(l_group_name, ".del")) { + if(dap_fnmatch("*.del", l_group_name, 0)) { const char *l_history_group = dap_chain_global_db_add_history_extra_group(l_group_name, PVT(l_net)->gdb_sync_nodes_addrs, &PVT(l_net)->gdb_sync_nodes_addrs_count); @@ -1839,6 +1968,22 @@ dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id) } +/** + * @brief dap_chain_net_by_id + * @param a_id + * @return + */ +uint16_t dap_chain_net_acl_idx_by_id(dap_chain_net_id_t a_id) +{ + dap_chain_net_item_t * l_net_item = NULL; + HASH_FIND(hh,s_net_items_ids,&a_id,sizeof (a_id), l_net_item ); + if (l_net_item) + return PVT(l_net_item->chain_net)->acl_idx; + else + return -1; + +} + /** * @brief dap_chain_net_id_by_name @@ -2397,3 +2542,77 @@ void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_da }break; } } + +static bool s_net_check_acl(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_pkey_hash) +{ + const char l_path[] = "network/"; + char l_cfg_path[strlen(a_net->pub.name) + strlen(l_path) + 1]; + strcpy(l_cfg_path, l_path); + strcat(l_cfg_path, a_net->pub.name); + dap_config_t *l_cfg = dap_config_open(l_cfg_path); + const char *l_auth_type = dap_config_get_item_str(l_cfg, "auth", "type"); + bool l_authorized = true; + if (l_auth_type && !strcmp(l_auth_type, "ca")) { + if (dap_hash_fast_is_blank(a_pkey_hash)) { + return false; + } + l_authorized = false; + const char *l_auth_hash_str = dap_chain_hash_fast_to_str_new(a_pkey_hash); + uint16_t l_acl_list_len = 0; + char **l_acl_list = dap_config_get_array_str(l_cfg, "auth", "acl_accept_ca_list", &l_acl_list_len); + for (uint16_t i = 0; i < l_acl_list_len; i++) { + if (!strcmp(l_acl_list[i], l_auth_hash_str)) { + l_authorized = true; + break; + } + } + if (!l_authorized) { + const char *l_acl_gdb = dap_config_get_item_str(l_cfg, "auth", "acl_accept_ca_gdb"); + if (l_acl_gdb) { + size_t l_objs_count; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_acl_gdb, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + if (!strcmp(l_objs[i].key, l_auth_hash_str)) { + l_authorized = true; + break; + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + } + } + if (!l_authorized) { + const char *l_acl_chains = dap_config_get_item_str(l_cfg, "auth", "acl_accept_ca_chains"); + if (l_acl_chains && !strcmp(l_acl_chains, "all")) { + dap_list_t *l_certs = dap_cert_get_all_mem(); + for (dap_list_t *l_tmp = l_certs; l_tmp; l_tmp = dap_list_next(l_tmp)) { + dap_cert_t *l_cert = (dap_cert_t *)l_tmp->data; + size_t l_pkey_size; + uint8_t *l_pkey_ser = dap_enc_key_serealize_pub_key(l_cert->enc_key, &l_pkey_size); + dap_chain_hash_fast_t l_cert_hash; + dap_hash_fast(l_pkey_ser, l_pkey_size, &l_cert_hash); + if (!memcmp(l_pkey_ser, a_pkey_hash, sizeof(dap_chain_hash_fast_t))) { + l_authorized = true; + DAP_DELETE(l_pkey_ser); + break; + } + DAP_DELETE(l_pkey_ser); + } + } + } + } + return l_authorized; +} + +static uint8_t *dap_chain_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash) +{ + uint16_t l_net_count; + dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count); + if (l_net_count) { + uint8_t *l_ret = DAP_NEW_SIZE(uint8_t, l_net_count); + for (uint16_t i = 0; i < l_net_count; i++) { + l_ret[i] = s_net_check_acl(l_net_list[i], a_pkey_hash); + } + return l_ret; + } + return NULL; +} diff --git a/modules/net/dap_chain_net_bugreport.c b/modules/net/dap_chain_net_bugreport.c deleted file mode 100644 index 3c284980b6282a707852367cf79caf3495d1d2d1..0000000000000000000000000000000000000000 --- a/modules/net/dap_chain_net_bugreport.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Authors: - * Alexander Lysikov <alexander.lysikov@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2020 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. - */ -#include <stdlib.h> -#include <stdio.h> -#include <time.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdint.h> - -#include "dap_common.h" -#include "dap_string.h" -#include "dap_strfuncs.h" -#include "dap_file_utils.h" -#include "dap_config.h" -#include "rand/dap_rand.h" - -#include "http_status_code.h" -#include "dap_http_simple.h" -#include "dap_enc_http.h" -#include "dap_chain_net_bugreport.h" - -#define LOG_TAG "chain_net_bugreport" - -#define BUGREPORT_URL "/bugreport" - -static int64_t bugreport_write_to_file(byte_t *a_request_byte, size_t a_request_size) -{ - int64_t l_report_number = -2; - if(!a_request_byte || !a_request_size) - return -1; - char *l_dir_str = dap_strdup_printf("%s/var/bugreport", g_sys_dir_path); - dap_mkdir_with_parents(l_dir_str); - - const time_t l_timer = time(NULL); - struct tm l_tm; - localtime_r(&l_timer, &l_tm); - randombytes(&l_report_number, sizeof(int64_t)); - if(l_report_number<0) - l_report_number = -l_report_number; - // create unique number for bugreport - l_report_number -= l_report_number%1000000000000ll; - l_report_number+=(int64_t)(l_tm.tm_year - 100)*10000000000; - l_report_number+=(int64_t)(l_tm.tm_mon)*100000000; - l_report_number+=(int64_t)(l_tm.tm_mday)*1000000; - l_report_number+=(int64_t)(l_tm.tm_hour)*10000; - l_report_number+=(int64_t)(l_tm.tm_min)*100; - l_report_number+=(int64_t)(l_tm.tm_sec); - char *l_filename_str = dap_strdup_printf("%s/%02d-%02d-%02d_%02d:%02d:%02d_%08lld.brt", l_dir_str, - l_tm.tm_year - 100, l_tm.tm_mon, l_tm.tm_mday, - l_tm.tm_hour, l_tm.tm_min, l_tm.tm_sec, - l_report_number); - FILE *l_fp; - if((l_fp = fopen(l_filename_str, "wb")) != NULL) { - if(fwrite(a_request_byte, 1, a_request_size, l_fp) != a_request_size) - l_report_number = -3; - fclose(l_fp); - } - DAP_DELETE(l_filename_str); - DAP_DELETE(l_dir_str); - return l_report_number; -} - -/** - * @brief bugreport_http_proc - * @param a_http_simple - * @param a_arg - */ -static void bugreport_http_proc(struct dap_http_simple *a_http_simple, void * a_arg) -{ - // data:text/html,<form action=http://192.168.100.92:8079/bugreport/ method=post><input name=a></form> - // data:text/html,<form action=http://cdb.klvn.io/bugreport/ method=post><input name=a></form> - log_it(L_DEBUG, "bugreport_http_proc request"); - http_status_code_t * return_code = (http_status_code_t*) a_arg; - //if(dap_strcmp(cl_st->http->url_path, BUGREPORT_URL) == 0 ) - if(dap_strcmp(a_http_simple->http->action, "GET") == 0) { - size_t l_url_len = dap_strlen(a_http_simple->http->url_path); - if(!l_url_len) { - a_http_simple->reply = dap_strdup_printf("Unique Bug Report number required)"); - *return_code = Http_Status_NotFound; - } - else{ - *return_code = Http_Status_OK; - } - a_http_simple->reply_size = strlen(a_http_simple->reply); - *return_code = Http_Status_NotFound; - } - if(dap_strcmp(a_http_simple->http->action, "POST") == 0) { - //a_http_simple->request_byte; - //a_http_simple->request_size; - //a_http_simple->http->in_content_length; - - int64_t l_bugreport_number = bugreport_write_to_file(a_http_simple->request_byte, a_http_simple->request_size); - if(l_bugreport_number >= 0) { - a_http_simple->reply = dap_strdup_printf("Bug Report #%020lld saved successfully)", l_bugreport_number); - } - else { - a_http_simple->reply = dap_strdup_printf("Bug Report not saved( code=%lld", l_bugreport_number); - } - a_http_simple->reply_size = strlen(a_http_simple->reply); - *return_code = Http_Status_OK; - - } else { - log_it(L_ERROR, "Wrong action '%s' for the request. Must be 'POST'", a_http_simple->http->action); - a_http_simple->reply = dap_strdup_printf("Wrong action '%s' for the request. Must be 'POST'", - a_http_simple->http->action); - a_http_simple->reply_size = strlen(a_http_simple->reply); - *return_code = Http_Status_NotFound; - } -} - -/** - * @brief dap_chain_net_bugreport_add_proc - * @param sh HTTP server instance - */ -void dap_chain_net_bugreport_add_proc(struct dap_http * sh) -{ - const char * url = BUGREPORT_URL; - dap_http_simple_proc_add(sh, url, 14096, bugreport_http_proc); -} - diff --git a/modules/net/dap_chain_net_news.c b/modules/net/dap_chain_net_news.c deleted file mode 100644 index 8c4984ae9bda0160d89c2ad63366971542d85f9b..0000000000000000000000000000000000000000 --- a/modules/net/dap_chain_net_news.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Authors: - * Alexander Lysikov <alexander.lysikov@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2020 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stddef.h> - -#include "dap_common.h" -#include "dap_string.h" -#include "dap_strfuncs.h" -#include "dap_file_utils.h" -#include "dap_config.h" - -#include "http_status_code.h" -#include "dap_http_simple.h" -#include "dap_enc_http.h" -//#include "<dap_chain_global_db_driver.h> -#include "dap_chain_global_db.h" -#include "dap_chain_net_news.h" -#define LOG_TAG "chain_net_news" - -#define NEWS_URL "/news" -#define GROUP_NEWS "cdb.news" -#define DEFAULT_LANG "en" - -/* Set news in the selected language - * a_lang - a language like "en", "ru", "fr" - * a_data_news - news data - * a_data_news_len length of news - */ -int dap_chain_net_news_write(const char *a_lang, char *a_data_news, size_t a_data_news_len) -{ - if(!a_data_news || !a_data_news_len) - return -2; - if(!a_lang) - a_lang = DEFAULT_LANG; - if(dap_chain_global_db_gr_set(dap_strdup(a_lang), a_data_news, a_data_news_len, GROUP_NEWS)) - return 0; - return -1; -} - -/* Get news in the selected language - * a_lang - a language like "en", "ru", "fr" - */ -byte_t* dap_chain_net_news_read(const char *a_lang, size_t *a_news_len) -{ - if(!a_lang) - return NULL; - byte_t *l_ret_data = NULL; - size_t l_data_len_num = 0; - dap_store_obj_t *l_obj = dap_chain_global_db_obj_gr_get(a_lang, &l_data_len_num, GROUP_NEWS); - if(l_obj && l_obj->value_len) { - l_ret_data = DAP_NEW_Z_SIZE(byte_t, l_obj->value_len); - memcpy(l_ret_data, l_obj->value, l_obj->value_len); - if(a_news_len) - *a_news_len = l_obj->value_len; - } - dap_store_obj_free(l_obj, l_data_len_num); - return l_ret_data; -} - -/** - * @brief news_http_proc - * @param a_http_simple - * @param a_arg - */ -static void news_http_proc(struct dap_http_simple *a_http_simple, void * a_arg) -{ - log_it(L_DEBUG, "news_http_proc request"); - http_status_code_t * return_code = (http_status_code_t*) a_arg; - const char *l_lang = DEFAULT_LANG; - if(dap_strcmp(a_http_simple->http->url_path, NEWS_URL)) { - l_lang = a_http_simple->http->url_path; - } - - if(l_lang) - { - size_t l_news_data_len = 0; - // get news in the selected language - byte_t *l_news_data = dap_chain_net_news_read(l_lang, &l_news_data_len); - // get news in the default language - if(!l_news_data && dap_strcmp(a_http_simple->http->in_query_string, "LocalNewsOnly")) - l_news_data = dap_chain_net_news_read(DEFAULT_LANG, &l_news_data_len); - if( l_news_data){ - a_http_simple->reply = l_news_data ; - a_http_simple->reply_size = l_news_data_len; - }else{ - a_http_simple->reply = dap_strdup("no news"); - a_http_simple->reply_size = dap_strlen((char*) a_http_simple->reply) + 1; - } - *return_code = Http_Status_OK; - } - else { - log_it(L_ERROR, "Wrong request. Must be %s/<lang_code>, example http:/<addr>%s/en", NEWS_URL, NEWS_URL); - a_http_simple->reply = dap_strdup_printf("Wrong request. Must be %s/<lang_code>, example http:/<addr>%s/en", - NEWS_URL, NEWS_URL); - a_http_simple->reply_size = strlen(a_http_simple->reply); - *return_code = Http_Status_NotFound; - } -} - -/** - * @brief dap_chain_net_news_add_proc - * @param sh HTTP server instance - */ -void dap_chain_net_news_add_proc(struct dap_http * sh) -{ - const char * url = NEWS_URL; - dap_http_simple_proc_add(sh, url, 14096, news_http_proc); -} - diff --git a/modules/net/dap_chain_net_news.h b/modules/net/dap_chain_net_news.h index 08bd6ebb2be1eb3024e75431db97c0f7a60d02a2..409063d83e76198351aee2916537c25dcac049ef 100644 --- a/modules/net/dap_chain_net_news.h +++ b/modules/net/dap_chain_net_news.h @@ -24,16 +24,4 @@ #include "dap_http.h" -/* Set news in the selected language - * a_lang - a language like "en", "ru", "fr" - * a_data_news - news data - * a_data_news_len length of news - */ -int dap_chain_net_news_write(const char *a_lang, char *a_data_news, size_t a_data_news_len); - -/* Get news in the selected language - * a_lang - a language like "en", "ru", "fr" - */ -byte_t* dap_chain_net_news_read(const char *a_lang, size_t *a_news_len); - -void dap_chain_net_news_add_proc(struct dap_http * sh); +int dap_chain_net_news_init(dap_http_t * a_http); diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index 8ff96efa9d66ebc2989019ef650f744a4102e7c4..3ecd46abc29c7c3e132f1f95be4751f774164818 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -948,11 +948,6 @@ int dap_chain_node_cli_init(dap_config_t * g_config) dap_chain_node_cli_cmd_item_create("tx_history", com_tx_history, NULL, "Transaction history (for address or by hash)", "tx_history [-addr <addr> | -w <wallet name> | -tx <tx_hash>] -net <net name> -chain <chain name>\n"); - // vpn client - dap_chain_node_cli_cmd_item_create ("vpn_client", com_vpn_client, NULL, "VPN client control", - "vpn_client [start -addr <server address> -port <server port>| stop | status] -net <net name>\n"); - - // Log dap_chain_node_cli_cmd_item_create ("print_log", com_print_log, NULL, "Print log info", "print_log [ts_after <timestamp >] [limit <line numbers>]\n" ); @@ -965,11 +960,6 @@ int dap_chain_node_cli_init(dap_config_t * g_config) dap_chain_node_cli_cmd_item_create ("exit", com_exit, NULL, "Stop application and exit", "exit\n" ); -//#ifndef _WIN32 - // News - dap_chain_node_cli_cmd_item_create("news", com_news, NULL, "Add News for VPN clients. Language code is a text code like \"en\", \"ru\", \"fr\"", - "news [-text <news text> | -file <filename with news>] -lang <language code> \n"); -//#endif // create thread for waiting of clients pthread_t l_thread_id; diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index afbd4469e650b599851c52441c2c6f92f89a0128..8e79e0e6a3eb1db6076d153ea77991f539a40ab7 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -77,7 +77,6 @@ #include "dap_chain_net_srv.h" #ifndef _WIN32 #include "dap_chain_net_news.h" -#include "dap_chain_net_vpn_client.h" #endif #include "dap_chain_cell.h" @@ -1969,6 +1968,35 @@ int com_token_decl_sign(int argc, char ** argv, void *arg_func, char ** a_str_re } } +void s_com_mempool_list_print_for_chain(const dap_chain_net_t * a_net, const dap_chain_t * a_chain, dap_string_t * a_str_tmp){ + char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(a_chain); + if(!l_gdb_group_mempool){ + dap_string_append_printf(a_str_tmp, "%s.%s: chain not found\n", a_net->pub.name, a_chain->name); + }else{ + size_t l_objs_size = 0; + dap_global_db_obj_t * l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool, &l_objs_size); + if(l_objs_size > 0) + dap_string_append_printf(a_str_tmp, "%s.%s: Found %u records :\n", a_net->pub.name, a_chain->name, + l_objs_size); + else + dap_string_append_printf(a_str_tmp, "%s.%s: Not found records\n", a_net->pub.name, a_chain->name); + for(size_t i = 0; i < l_objs_size; i++) { + dap_chain_datum_t * l_datum = (dap_chain_datum_t*) l_objs[i].value; + char buf[50]; + time_t l_ts_create = (time_t) l_datum->header.ts_create; + dap_string_append_printf(a_str_tmp, "%s: type_id=%s data_size=%u ts_create=%s", // \n included in timestamp + l_objs[i].key, c_datum_type_str[l_datum->header.type_id], + l_datum->header.data_size, ctime_r(&l_ts_create, buf)); + + dap_chain_net_dump_datum(a_str_tmp, l_datum); + } + + dap_chain_global_db_objs_delete(l_objs, l_objs_size); + } + + DAP_DELETE(l_gdb_group_mempool); +} + /** * @brief com_token_decl_list * @param argc @@ -1994,43 +2022,14 @@ int com_mempool_list(int argc, char ** argv, void *arg_func, char ** a_str_reply } if(l_net) { - char * l_gdb_group_mempool = NULL, *l_gdb_group_mempool_tmp; - if(l_chain) { - l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain); - l_gdb_group_mempool_tmp = l_gdb_group_mempool; - } dap_string_t * l_str_tmp = dap_string_new(NULL); - DL_FOREACH(l_net->pub.chains, l_chain) { - if(!l_gdb_group_mempool) { - l_gdb_group_mempool_tmp = dap_chain_net_get_gdb_group_mempool(l_chain); - } - size_t l_objs_size = 0; - dap_global_db_obj_t * l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool_tmp, &l_objs_size); - if(l_objs_size > 0) - dap_string_append_printf(l_str_tmp, "%s.%s: Found %u records :\n", l_net->pub.name, l_chain->name, - l_objs_size); - else - dap_string_append_printf(l_str_tmp, "%s.%s: Not found records\n", l_net->pub.name, l_chain->name); - for(size_t i = 0; i < l_objs_size; i++) { - dap_chain_datum_t * l_datum = (dap_chain_datum_t*) l_objs[i].value; - char buf[50]; - time_t l_ts_create = (time_t) l_datum->header.ts_create; - dap_string_append_printf(l_str_tmp, "%s: type_id=%s data_size=%u ts_create=%s", // \n included in timestamp - l_objs[i].key, c_datum_type_str[l_datum->header.type_id], - l_datum->header.data_size, ctime_r(&l_ts_create, buf)); + if(l_chain) + s_com_mempool_list_print_for_chain(l_net, l_chain, l_str_tmp); + else + DL_FOREACH(l_net->pub.chains, l_chain) + s_com_mempool_list_print_for_chain(l_net, l_chain, l_str_tmp); - dap_chain_net_dump_datum(l_str_tmp, l_datum); - } - // Clean up - dap_chain_global_db_objs_delete(l_objs, l_objs_size); - if (l_gdb_group_mempool_tmp) - DAP_DELETE(l_gdb_group_mempool_tmp); - // only one time if group defined - if(l_gdb_group_mempool) { - break; - } - } dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str); dap_string_free(l_str_tmp, false); @@ -3756,206 +3755,3 @@ int com_print_log(int argc, char ** argv, void *arg_func, char **str_reply) return 0; } -/** - * Add News for VPN clients - * news [-text <news text> | -file <filename with news>] -lang <language code> - */ -int com_news(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply) -{ - int arg_index = 1; - const char * l_str_lang = NULL; - const char * l_str_text = NULL; - const char * l_str_file = NULL; - dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-lang", &l_str_lang); - dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-text", &l_str_text); - dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-file", &l_str_file); - if(!l_str_text && !l_str_file) { - dap_chain_node_cli_set_reply_text(a_str_reply, "no source of news, add parameter -text or -file"); - return -1; - } - char *l_data_news; - size_t l_data_news_len = 0; - const char *l_from = NULL; - - if(l_str_text) { - l_data_news = dap_strdup(l_str_text); - l_data_news_len = dap_strlen(l_str_text); - l_from = "text"; - } - else if(l_str_file) { - if(dap_file_get_contents(l_str_file, &l_data_news,&l_data_news_len)) { - l_from = "file"; - } - else{ - dap_chain_node_cli_set_reply_text(a_str_reply, "Can't read file %s", l_str_file); - return -2; - } - } - - int l_res = dap_chain_net_news_write(l_str_lang, l_data_news, l_data_news_len); - if(l_res){ - dap_chain_node_cli_set_reply_text(a_str_reply, "Error, News cannot be added from %s", l_from); - return -3; - } - dap_chain_node_cli_set_reply_text(a_str_reply, "News added from %s successfully", l_from); - return 0; -} - -/** - * vpn_client command - * - * VPN client control - */ -int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) -{ -#ifndef _WIN32 - enum { - CMD_NONE, CMD_INIT, CMD_START, CMD_STOP, CMD_STATUS - }; - int l_arg_index = 1; - // find net - dap_chain_net_t *l_net = NULL; - if(dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, NULL, &l_net) < 0) - return -2; - - int cmd_num = CMD_NONE; - if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "init", NULL)) { - cmd_num = CMD_INIT; - } - if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "start", NULL)) { - cmd_num = CMD_START; - } - else if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "stop", NULL)) { - cmd_num = CMD_STOP; - } - else if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "status", NULL)) { - cmd_num = CMD_STATUS; - } - if(cmd_num == CMD_NONE) { - if(!a_argv[1]) - dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameters"); - else - dap_chain_node_cli_set_reply_text(a_str_reply, "parameter %s not recognized", a_argv[1]); - return -1; - } - - switch (cmd_num) - { - case CMD_INIT: { - const char * l_str_token = NULL; // token name - const char * l_str_value_datoshi = NULL; - const char * l_str_wallet = NULL; // wallet name - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_str_wallet); - if(!l_str_wallet) - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_str_wallet); - - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-token", &l_str_token); - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_str_value_datoshi); - - if(!l_str_wallet) { - dap_chain_node_cli_set_reply_text(a_str_reply, "Wallet not defined, use -w <wallet_name> or -wallet <wallet_name> parameter"); - break; - } - if(!l_str_token) { - dap_chain_node_cli_set_reply_text(a_str_reply, "Token not defined, use -token <token_name> parameter"); - break; - } - if(!l_str_value_datoshi) { - dap_chain_node_cli_set_reply_text(a_str_reply, "Value of datoshi not defined, use -value <value of datoshi> parameter"); - break; - } - uint64_t l_a_value_datoshi = strtoull(l_str_value_datoshi, NULL, 10); - if(!l_a_value_datoshi) - l_a_value_datoshi = strtoull(l_str_value_datoshi, NULL, 16); - if(!l_a_value_datoshi) { - dap_chain_node_cli_set_reply_text(a_str_reply, "Value of datoshi have to be more then 0"); - break; - } - int l_res = dap_chain_net_vpn_client_update(l_net, l_str_wallet, l_str_token, l_a_value_datoshi); - if(!l_res) - dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client init successfully"); - else{ - if(l_res==-3) - dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client init successfully, but probably not enough founds in the wallet"); - else - dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client not init"); - } - return l_res; - } - break; - case CMD_START: { - const char * l_str_addr = NULL; // for example, "192.168.100.93" - const char * l_str_port = NULL; // for example, "8079" - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr", &l_str_addr); - if(!l_str_addr) { - dap_chain_node_cli_set_reply_text(a_str_reply, - "VPN server address not defined, use -addr <vpn server ipv4 address> parameter"); - break; - } - dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-port", &l_str_port); - int l_srv_port = (l_str_port) ? (int) strtoll(l_str_port, 0, 10) : 0; - if(!l_srv_port) { - dap_chain_node_cli_set_reply_text(a_str_reply, - "VPN server port not defined, use -port <vpn server port> parameter"); - break; - } - int l_res = dap_chain_net_vpn_client_start(l_net, l_str_addr, NULL, l_srv_port); - switch (l_res) { - case 0: - dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client started successfully"); - break; - case 1: - dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client already started"); - break; - case -2: - case -3: - dap_chain_node_cli_set_reply_text(a_str_reply, "Can't connect to VPN server"); - break; - default: - dap_chain_node_cli_set_reply_text(a_str_reply, "Can't start VPN client"); - break; - } - return l_res; - } - break; - case CMD_STOP: { - int res = dap_chain_net_vpn_client_stop(); - if(!res) - dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client stopped successfully"); - else - dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client not stopped"); - return res; - } - break; - case CMD_STATUS: - { - char *l_wallet_name = NULL, *l_str_token = NULL; - uint64_t l_value_datoshi = 0; - dap_chain_net_vpn_client_get_wallet_info(l_net, &l_wallet_name, &l_str_token, &l_value_datoshi); - - const char *l_status_txt = ""; - switch (dap_chain_net_vpn_client_status()) { - case VPN_CLIENT_STATUS_NOT_STARTED: - l_status_txt = "VPN client not started"; - break; - case VPN_CLIENT_STATUS_STARTED: - l_status_txt = "VPN client started"; - break; - case VPN_CLIENT_STATUS_STOPPED: - l_status_txt = "VPN client stopped"; - break; - case VPN_CLIENT_STATUS_CONN_LOST: - l_status_txt = "VPN client lost connection"; - break; - default: - l_status_txt = "VPN client status unknown"; - break; - } - dap_chain_node_cli_set_reply_text(a_str_reply, "%s\nused:\nwallet:%s\nreceipt:%u*1e-9 %s", l_status_txt, - l_wallet_name, l_value_datoshi, l_str_token); - break; - } - } -#endif - return 0; -} diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 84d03e43b69081b38ff4302c70bf58ffb51650be..1c3fe94d75e7944768ed291173f5714867dc825a 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -477,6 +477,8 @@ dap_chain_node_client_t* dap_chain_client_connect(dap_chain_node_info_t *a_node_ l_node_client->remote_node_addr.uint64 = a_node_info->hdr.address.uint64; dap_client_set_active_channels(l_node_client->client, a_active_channels); + //dap_client_set_auth_cert(l_node_client->client, dap_cert_find_by_name("auth")); // TODO provide the certificate choice + int hostlen = 128; char host[hostlen]; if(a_node_info->hdr.ext_addr_v4.s_addr) diff --git a/modules/net/dap_dns_server.c b/modules/net/dap_dns_server.c index 33e4b54ef1e92c52e58646c4b552fe3189fc6aa7..143abd7ecdfeddde2e86c5058688b4a139c993ad 100644 --- a/modules/net/dap_dns_server.c +++ b/modules/net/dap_dns_server.c @@ -322,6 +322,9 @@ void dap_dns_server_start() { } void dap_dns_server_stop() { + if(!s_dns_server) + return; + dap_dns_zone_hash_t *current_zone, *tmp; HASH_ITER(hh, s_dns_server->hash_table, current_zone, tmp) { HASH_DEL(s_dns_server->hash_table, current_zone); diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index b2cdeef5cbf3823738ad56f9e1b65860c1904a62..941019b63282482e9f5c6cd61dc7d59b69c32412 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -102,6 +102,7 @@ void dap_chain_net_proc_mempool (dap_chain_net_t * a_net); dap_chain_net_t * dap_chain_net_by_name( const char * a_name); dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id); +uint16_t dap_chain_net_acl_idx_by_id(dap_chain_net_id_t a_id); dap_chain_net_id_t dap_chain_net_id_by_name( const char * a_name); dap_ledger_t * dap_chain_ledger_by_net_name( const char * a_net_name); @@ -114,8 +115,6 @@ dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net); dap_list_t* dap_chain_net_get_link_node_list(dap_chain_net_t * l_net, bool a_is_only_cur_cell); dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net); -void dap_chain_net_links_connect(dap_chain_net_t * a_net); - typedef enum dap_chain_net_tx_search_type { /// Search local, in memory, possible load data from drive to memory TX_SEARCH_TYPE_LOCAL, diff --git a/modules/net/include/dap_chain_net_bugreport.h b/modules/net/include/dap_chain_net_bugreport.h index 00f4c2d9f6d8d5271b8f80a76591e107232a1020..c930015f0b79897ba7502452b74da80595b89872 100644 --- a/modules/net/include/dap_chain_net_bugreport.h +++ b/modules/net/include/dap_chain_net_bugreport.h @@ -24,4 +24,4 @@ #include "dap_http.h" -void dap_chain_net_bugreport_add_proc(struct dap_http * sh); +int dap_chain_net_bugreport_init(dap_http_t * a_http); diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h index dc5f569568a615c76df8732a082f3a29e8208b84..a5be2cd0f863195bf39ccb6ea53c1f5ac78f9a03 100644 --- a/modules/net/include/dap_chain_node_cli_cmd.h +++ b/modules/net/include/dap_chain_node_cli_cmd.h @@ -133,14 +133,6 @@ int com_stats(int argc, char ** argv, void *arg_func, char **str_reply); int com_exit(int argc, char ** argv, void *arg_func, char **str_reply); -//#ifndef _WIN32 -// Add News for VPN clients -int com_news(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply); -//#endif - -// vpn_client command -int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply); - int com_mempool_delete(int argc, char ** argv, void *arg_func, char ** a_str_reply); int com_mempool_list(int argc, char ** argv, void *arg_func, char ** a_str_reply); int com_mempool_proc(int argc, char ** argv, void *arg_func, char ** a_str_reply); diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index 666a5dc2e3f855b525743730dbd1d8cc58d88116..10db028050013b28ac642d57ce77e109cad90cdd 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -510,7 +510,6 @@ static int s_callback_response_success(dap_chain_net_srv_t * a_srv, uint32_t a_u pthread_rwlock_init(&l_usage_client->rwlock,NULL); memcpy(l_usage_client->receipt, l_receipt, l_receipt_size); - pthread_rwlock_wrlock(&s_clients_rwlock); HASH_ADD(hh, s_clients,usage_id,sizeof(a_usage_id),l_usage_client); @@ -686,7 +685,7 @@ void s_new(dap_stream_ch_t* a_stream_ch, void* a_arg) */ void srv_ch_vpn_delete(dap_stream_ch_t* ch, void* arg) { - log_it(L_DEBUG, "ch_sf_delete() for %s", ch->stream->conn->hostaddr); + log_it(L_DEBUG, "ch_sf_delete() for %s", ch->stream->conn->s_ip); dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(ch); dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_ch_vpn->net_srv->_inhertor; pthread_mutex_lock(&(l_ch_vpn->mutex)); @@ -703,7 +702,6 @@ void srv_ch_vpn_delete(dap_stream_ch_t* ch, void* arg) l_is_unleased = true; pthread_rwlock_unlock(& s_raw_server_rwlock); } - pthread_rwlock_wrlock(&s_clients_rwlock); if(s_ch_vpn_addrs) { HASH_DEL(s_ch_vpn_addrs, l_ch_vpn); @@ -720,7 +718,6 @@ void srv_ch_vpn_delete(dap_stream_ch_t* ch, void* arg) HASH_FIND(hh,s_clients, &l_ch_vpn->usage_id,sizeof(l_ch_vpn->usage_id),l_usage_client ); if (l_usage_client){ pthread_rwlock_wrlock(&l_usage_client->rwlock); - l_usage_client->ch_vpn = NULL; // NULL the channel, nobody uses that indicates pthread_rwlock_unlock(&l_usage_client->rwlock); } @@ -929,7 +926,7 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) //if ( pkt->hdr.type == DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT ) // dap_chain_net_vpn_client_pkt_in( a_ch, l_pkt); - if(l_pkt->hdr.type == DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA) { + if(l_pkt->hdr.type != DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT) { static bool client_connected = false; ch_vpn_pkt_t * l_vpn_pkt = (ch_vpn_pkt_t *) l_pkt->data; size_t l_vpn_pkt_size = l_pkt->hdr.size - sizeof (l_vpn_pkt->header); @@ -1611,7 +1608,7 @@ void* srv_ch_sf_thread_raw(void *arg) s_update_limits(l_ch_vpn->ch,l_srv_session,l_usage, l_read_ret); } } - pthread_rwlock_unlock(&s_clients_rwlock); + pthread_rwlock_unlock(&s_clients_rwlock);\ } }/*else { log_it(L_CRITICAL,"select() has no tun handler in the returned set"); diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb.c deleted file mode 100644 index 648b707b267e9aa3957dd463eab892da7cc36551..0000000000000000000000000000000000000000 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * CellFrame https://cellframe.net - * Sources https://gitlab.demlabs.net/cellframe - * Copyright (c) 2017-2019 - * All rights reserved. - - This file is part of CellFrame SDK the open source project - - CellFrame SDK is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CellFrame SDK is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#include "utlist.h" -#include "dap_common.h" -#include "dap_config.h" -#include "dap_enc_http.h" -#include "dap_enc_base64.h" -#include "dap_http.h" - -#include "dap_chain.h" -#include "dap_chain_net.h" -#include "dap_chain_ledger.h" -#include "dap_chain_wallet.h" -#include "dap_chain_datum_tx.h" -#include "dap_chain_datum_tx_in.h" -#include "dap_chain_datum_tx_in_cond.h" -#include "dap_chain_datum_tx_out_cond.h" -#include "dap_chain_datum_tx_out.h" -#include "dap_chain_datum_tx_pkey.h" -#include "dap_chain_datum_tx_receipt.h" -#include "dap_chain_datum_tx_sig.h" -#include "dap_chain_global_db.h" - -#include "dap_chain_node_cli.h" - -#include "dap_chain_mempool.h" -#include "dap_pkey.h" - -#include "dap_chain_net_srv_vpn.h" -#include "dap_chain_net_srv_vpn_cdb.h" -#include "dap_chain_net_srv_vpn_cdb_auth.h" -#include "dap_chain_net_srv_vpn_cdb_server_list.h" - - -#define LOG_TAG "dap_chain_net_srv_vpn_cdb" - -#define DB_URL "/db" -#define NODELIST_URL "/nodelist" - -typedef struct tx_cond_template{ - char * wallet_name; - dap_chain_wallet_t * wallet; - - long double value_coins; - uint128_t value_datoshi; - - char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; - char * net_name; - dap_chain_net_t * net; - dap_ledger_t * ledger; - time_t min_time; // Minimum time between transactions - struct tx_cond_template *prev, *next; -} tx_cond_template_t; - -static tx_cond_template_t *s_tx_cond_templates = NULL; -const char *c_wallets_path = NULL; - -static int s_cli_vpn_cdb(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply); - -/** - * @brief dap_chain_net_srv_vpn_cdb_init - * @return - */ -int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http) -{ - int ret=0; - c_wallets_path = dap_chain_wallet_get_path(g_config); - if (dap_config_get_item_bool_default( g_config, - "cdb", - "servers_list_enabled", - false)) { - - if (dap_chain_net_srv_vpn_cdb_server_list_init() != 0) { - log_it(L_CRITICAL,"Can't init vpn servers list"); - return -10; - } - } - - dap_chain_node_cli_cmd_item_create ("vpn_cdb", s_cli_vpn_cdb, NULL, "VPN Central DataBase (CDB) commands", - "vpn_cdb user create --login <Login> --password <Password> [--first_name <First Name] [--last_name <Last Name>] [--email <Email>]" - "[--acive_days <Setup active day thats left for user >]\n" - "\tCreate user with login, password and some more optional fields\n\n" - "vpn_cdb user update --login <Login> [--password <Password>] [--first_name <First Name] [--last_name <Last Name>] [--email <Email>]" - "[--active_days <Setup active days that left for user >]\n" - "\tUpdate existent user\n" - "vpn_cdb user delete --login <Login>\n" - "\tDelete user by login\n" - "vpn_cdb user show --login <Login>\n" - "\tShow user fields by login\n" - "vpn_cdb user check --login <Login> --password <Password>\n" - "\tCompare <Password> with stored in GDB for <Login>\n" - "vpn_cdb user list\n" - "\tShow all users\n" - "vpn_cdb serial generate -n <number of serial keys>] [-acive_days <active days that left for serial>]\n" - "\tGenerate new serial keys\n" - "vpn_cdb serial list [-n <How many show serial keys>] [-shift <How many skip serial keys>] [-nototal]\n" - "\tShow serial keys\n" - "vpn_cdb serial update -serial <serial keys> -acive_days <active days that left for serial>\n" - "\tEdit serial key\n" - ); - - // Load all chain networks - if (dap_config_get_item_bool_default( g_config, - "cdb", - "servers_list_enabled", - false)) { - dap_chain_net_srv_vpn_cdb_server_list_add_proc ( a_http, NODELIST_URL); - } - if (dap_config_get_item_bool_default( g_config,"cdb_auth","enabled",false) ){ - - ret = dap_chain_net_srv_vpn_cdb_auth_init( dap_config_get_item_str_default(g_config,"cdb_auth","domain","cdb"), - dap_config_get_item_str_default(g_config,"cdb_auth","mode","passwd"), - dap_config_get_item_bool_default(g_config,"cdb_auth","registration_open",false)); - if(ret<0) - return ret; - dap_chain_net_srv_vpn_cdb_auth_add_proc( a_http , DB_URL ); - - // Produce transaction for authorized users - if (dap_config_get_item_bool_default( g_config, - "cdb_auth", - "tx_cond_create", - false)) { - // Parse tx cond templates - uint16_t l_tx_cond_tpls_count = 0; - - /* ! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data - * ! it also must NOT be freed within this module ! - */ - char **l_tx_cond_tpls = dap_config_get_array_str(g_config, "cdb_auth", "tx_cond_templates", &l_tx_cond_tpls_count); - if (l_tx_cond_tpls_count == 0) { - log_it( L_ERROR, "No condition tpl, can't setup auth callback"); - return -5; - } - - for (size_t i = 0 ; i < l_tx_cond_tpls_count; i++) { - tx_cond_template_t *l_tx_cond_template = DAP_NEW_Z(tx_cond_template_t); - - // Parse template entries - short l_step = 0; - char *ctx; - for (char *l_tpl_token = strtok_r(l_tx_cond_tpls[i], ":", &ctx); l_tpl_token || l_step == 5; l_tpl_token = strtok_r(NULL, ":", &ctx), ++l_step) { - switch (l_step) { - case 0: - if(!(l_tx_cond_template->wallet = dap_chain_wallet_open(l_tpl_token, c_wallets_path))) { - log_it(L_ERROR, "Can't open wallet \"%s\"", l_tpl_token); - DAP_DELETE(l_tx_cond_template); - break; - } - l_tx_cond_template->wallet_name = l_tpl_token; - continue; - case 1: - if (!(l_tx_cond_template->value_coins = strtold(l_tpl_token, NULL))) { - log_it(L_ERROR, "Error parsing tpl: text on 2nd position \"%s\" is not a number", l_tpl_token); - DAP_DELETE(l_tx_cond_template->wallet); - DAP_DELETE(l_tx_cond_template); - l_step = 0; - break; - } - l_tx_cond_template->value_datoshi = dap_chain_coins_to_balance(l_tx_cond_template->value_coins); - continue; - case 2: - if (!(l_tx_cond_template->min_time = (time_t)atoll(l_tpl_token))) { - log_it(L_ERROR, "Error parsing tpl: text on 3d position \"%s\" is not a number", l_tpl_token); - DAP_DELETE(l_tx_cond_template->wallet); - DAP_DELETE(l_tx_cond_template); - l_step = 0; - break; - } - continue; - case 3: - dap_stpcpy(l_tx_cond_template->token_ticker, l_tpl_token); - continue; - case 4: - if (!(l_tx_cond_template->net = dap_chain_net_by_name(l_tpl_token)) - || !(l_tx_cond_template->ledger = dap_chain_ledger_by_net_name(l_tpl_token))) - { - log_it(L_ERROR, "Can't open network \"%s\" or ledger in it", l_tpl_token); - DAP_DELETE(l_tx_cond_template->wallet); - DAP_DELETE(l_tx_cond_template); - l_step = 0; - break; - } - l_tx_cond_template->net_name = l_tpl_token; - continue; - case 5: - log_it(L_INFO, "Condition template correct, added to list"); - DL_APPEND(s_tx_cond_templates, l_tx_cond_template); - break; - default: - break; - } - log_it(L_DEBUG, "Done with tpl item %d", i); - break; // double break exits tokenizer loop and steps to next tpl item - } - } - if (!s_tx_cond_templates) ret = -1; - } else { - log_it(L_INFO, "No conditional transactions, provide VPN service for free"); - } - } - return ret; -} - -static int s_cli_vpn_cdb(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) -{ - const char *l_user_str = NULL; - const char *l_serial_add_param_str = NULL; - int l_arg_index = 1; - int l_ret = -1; - - int l_user_pos = dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "user", &l_user_str); - int l_serial_pos = dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "serial", &l_serial_add_param_str); - - - // Selected 'user' subcommand - if ( l_user_str ){ - l_ret = 0; - return dap_chain_net_srv_vpn_cdb_auth_cli_cmd_user(l_user_str,l_arg_index, a_argc, a_argv,a_str_reply); - } - // Selected 'serial' subcoummand - else if(l_serial_add_param_str) { - l_ret = 0; - return dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial(l_serial_add_param_str, l_arg_index, a_argc, a_argv, a_str_reply); - } - else { - if(l_user_pos || l_user_pos) - dap_chain_node_cli_set_reply_text(a_str_reply, "require additional subcommand, see 'help vpn_cdb'"); - else - dap_chain_node_cli_set_reply_text(a_str_reply, "unknown subcommand, use 'user' or 'serial'", l_user_str); - } - return l_ret; -} - - -/** - * @brief dap_chain_net_srv_vpn_cdb_deinit - */ -void dap_chain_net_srv_vpn_cdb_deinit() -{ - -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_after - * @param a_delegate - * @param a_login - * @param a_pkey_b64 - */ -void dap_chain_net_srv_vpn_cdb_auth_after(enc_http_delegate_t* a_delegate, const char * a_login, const char * a_pkey_b64 ) -{ -#ifndef __ANDROID__ - - dap_enc_key_t *l_client_key = NULL; - byte_t *l_pkey_raw = NULL; - size_t l_pkey_raw_size = 0; - log_it( L_DEBUG, "Authorized, now need to create conditioned transaction if not present key_len=%d", dap_strlen( a_pkey_b64)); - { - size_t l_pkey_b64_length = dap_strlen( a_pkey_b64); - l_pkey_raw = DAP_NEW_Z_SIZE(byte_t,l_pkey_b64_length); - memset(l_pkey_raw, 0, l_pkey_b64_length); - l_pkey_raw_size = dap_enc_base64_decode(a_pkey_b64, l_pkey_b64_length, l_pkey_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); - char *l_pkey_gdb_group = dap_strdup_printf( "cdb.%s.pkey", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); - log_it(L_DEBUG, "Pkey group '%s'", l_pkey_gdb_group); - dap_chain_global_db_gr_set( dap_strdup(a_login), l_pkey_raw, l_pkey_raw_size, l_pkey_gdb_group); - - l_client_key = dap_enc_key_new(DAP_ENC_KEY_TYPE_SIG_TESLA); - int l_res = dap_enc_key_deserealize_pub_key(l_client_key, l_pkey_raw, l_pkey_raw_size); - // bad pkey - if(l_res){ - log_it(L_WARNING, "dap_enc_key_deserealize_priv_key='%d'", l_res); - DAP_DELETE(l_pkey_raw); - l_pkey_raw_size = 0; - l_pkey_raw = NULL; - } - DAP_DELETE(l_pkey_gdb_group); - } - - tx_cond_template_t *l_tpl; - DL_FOREACH(s_tx_cond_templates, l_tpl) { - size_t l_gdb_group_size = 0; - - // Try to load from gdb - //char *l_tx_cond_gdb_group = dap_strdup_printf( "%s.%s.tx_cond", l_tpl->net->pub.name, DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); - char *l_tx_cond_gdb_group = dap_strdup_printf( "cdb.%s.tx_cond", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); - log_it(L_DEBUG, "Checkout group %s", l_tx_cond_gdb_group); - // get key for tx_cond - char *l_user_key; - { - dap_chain_hash_fast_t l_hash = { 0 }; - char *l_key_hash_str = NULL; - if(dap_hash_fast(a_pkey_b64, dap_strlen(a_pkey_b64), &l_hash)) - l_key_hash_str = dap_chain_hash_fast_to_str_new(&l_hash); - l_user_key = dap_strdup_printf("%s/%s", a_login, l_key_hash_str); - DAP_DELETE(l_key_hash_str); - } - log_it(L_DEBUG, "\ndbg l_user_key=%s\n", l_user_key); - dap_chain_hash_fast_t *l_tx_cond_hash = (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get(l_user_key, &l_gdb_group_size, l_tx_cond_gdb_group); - - // Check for entry size - if (l_gdb_group_size && l_gdb_group_size != sizeof(dap_chain_hash_fast_t)) { - log_it(L_ERROR, "Wrong size of tx condition on database (%zd but expected %zd), may be old entry", - l_gdb_group_size, sizeof(dap_chain_hash_fast_t)); - } - - time_t l_tx_cond_ts = 0; - // If loaded lets check is it spent or not - if ( l_tx_cond_hash ){ - log_it(L_DEBUG, "2791: Search for unspent tx, net %s", l_tpl->net_name); - dap_chain_datum_tx_t *l_tx = dap_chain_net_get_tx_by_hash(l_tpl->net, l_tx_cond_hash, TX_SEARCH_TYPE_NET_UNSPENT); - if ( !l_tx ){ // If not found - all outs are used. Create new one - // pass all chains - l_tx = dap_chain_net_get_tx_by_hash(l_tpl->net, l_tx_cond_hash, TX_SEARCH_TYPE_NET); - DAP_DELETE(l_tx_cond_hash); - l_tx_cond_hash = NULL; - if ( l_tx ){ - l_tx_cond_ts =(time_t) l_tx->header.ts_created; - log_it(L_DEBUG, "2791: got some tx, created %d", l_tx->header.ts_created); - } - } - } - - // Try to create condition - if (! l_tx_cond_hash ) { - dap_chain_wallet_t *l_wallet_from = l_tpl->wallet; - log_it(L_DEBUG, "Create tx from wallet %s", l_wallet_from->name); - dap_enc_key_t *l_key_from = dap_chain_wallet_get_key(l_wallet_from, 0); - - - //dap_chain_cell_id_t *xccell = dap_chain_net_get_cur_cell(l_tpl->net); - //uint64_t uint64 =dap_chain_net_get_cur_cell(l_tpl->net)->uint64; - - - // where to take coins for service - dap_chain_addr_t *l_addr_from = dap_chain_wallet_get_addr(l_wallet_from, l_tpl->net->pub.id); - dap_chain_net_srv_price_unit_uid_t l_price_unit = { .enm = SERV_UNIT_SEC }; - dap_chain_net_srv_uid_t l_srv_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID }; - l_tx_cond_hash = dap_chain_proc_tx_create_cond(l_tpl->net, l_key_from, l_client_key, l_addr_from, l_tpl->token_ticker, - (uint64_t) l_tpl->value_datoshi, 0, l_price_unit, l_srv_uid, 0, l_pkey_raw, l_pkey_raw_size); - char *l_addr_from_str = dap_chain_addr_to_str( l_addr_from ); - DAP_DELETE( l_addr_from); - if (!l_tx_cond_hash) { - log_it(L_ERROR, "Can't create condition for user"); - } else { - // save transaction for login - dap_chain_global_db_gr_set(l_user_key, l_tx_cond_hash, sizeof(dap_chain_hash_fast_t), l_tx_cond_gdb_group); - log_it(L_NOTICE, "User \"%s\": created conditioned transaction from %s(%s) on " - , a_login, l_tpl->wallet_name, l_addr_from_str); - } - DAP_DELETE( l_addr_from_str ); - } - DAP_DELETE(l_user_key); - // dbg - //dap_ledger_t * l_ledger = dap_chain_ledger_by_net_name( l_tpl->net->pub.name); - //dap_chain_datum_tx_t *l_tx = dap_chain_ledger_tx_find_by_hash( l_ledger, l_tx_cond_hash); - - // If we loaded or created hash - if( l_tx_cond_hash ){ - char * l_tx_cond_hash_str = dap_chain_hash_fast_to_str_new(l_tx_cond_hash); - enc_http_reply_f(a_delegate,"\t<tx_cond_tpl>\n"); - //enc_http_reply_f(a_delegate,"\t\t<net>%s</net>\n",l_tpl->net_name); - enc_http_reply_f(a_delegate,"\t\t<net>0x%x</net>\n",l_tpl->net->pub.id.uint64); - enc_http_reply_f(a_delegate,"\t\t<token>%s</token>\n",l_tpl->token_ticker); - enc_http_reply_f(a_delegate,"\t\t<tx_cond>%s</tx_cond>\n",l_tx_cond_hash_str); - enc_http_reply_f(a_delegate,"\t</tx_cond_tpl>\n"); - DAP_DELETE(l_tx_cond_hash); - DAP_DELETE(l_tx_cond_hash_str); - } - - DAP_DELETE(l_tx_cond_gdb_group); - } - if (l_client_key) - dap_enc_key_delete(l_client_key); -#endif -} diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c deleted file mode 100644 index e44fbaf2f51da62c68e7c5885f0a5342098ad010..0000000000000000000000000000000000000000 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c +++ /dev/null @@ -1,1220 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * CellFrame https://cellframe.net - * Sources https://gitlab.demlabs.net/cellframe - * Copyright (c) 2017-2020 - * All rights reserved. - - This file is part of CellFrame SDK the open source project - - CellFrame SDK is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CellFrame SDK is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. -*/ - - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <sys/wait.h> -#include <rand/dap_rand.h> - -#include <time.h> - -#include "dap_common.h" -#include "dap_string.h" -#include "dap_strfuncs.h" -#include "dap_client_remote.h" - -#include "dap_http.h" -#include "dap_http_client.h" -#include "dap_http_simple.h" - -#include "dap_enc.h" -#include "dap_enc_key.h" -#include "dap_enc_ks.h" -#include "dap_enc_http.h" -#include "dap_enc_base64.h" -#include "dap_server.h" - -#include "dap_chain_node_cli.h" -#include "dap_chain_global_db.h" - -#include "http_status_code.h" - -#include "dap_chain_net_srv_vpn_cdb.h" -#include "dap_chain_net_srv_vpn_cdb_auth.h" - -#define LOG_TAG "dap_chain_net_srv_vpn_cdb_auth" - -#define OP_CODE_LOGIN_INCORRECT_PSWD "0xf2" -#define OP_CODE_LOGIN_INCORRECT_SIGN "0xf2" -#define OP_CODE_NOT_FOUND_LOGIN_IN_DB "0xf3" -#define OP_CODE_SUBSCRIBE_EXPIRIED "0xf4" -#define OP_CODE_INCORRECT_SYMOLS "0xf6" -#define OP_CODE_LOGIN_INACTIVE "0xf7" -#define OP_CODE_SERIAL_ACTIVED "0xf8" - - -dap_enc_http_callback_t s_callback_success = NULL; - -static char * s_domain = NULL; -static char * s_group_users = NULL; -static char * s_group_serials = NULL; -static char * s_group_serials_activated = NULL; - -static char * s_group_password = NULL; -static char * s_group_first_name = NULL; -static char * s_group_last_name = NULL; -static char * s_group_email = NULL; -static char * s_group_ts_updated = NULL; -static char * s_group_ts_last_login = NULL; -static char * s_group_cookies = NULL; -static char * s_group_cookie = NULL; -static char * s_group_ts_active_till = NULL; - -static char * s_salt_str = "Ijg24GAS56h3hg7hj245b"; - -static bool s_is_registration_open = false; -static bool s_mode_passwd = true; - -static int s_input_validation(const char * str); -static void s_http_enc_proc(enc_http_delegate_t *a_delegate, void * a_arg); -static void s_http_enc_proc_key(enc_http_delegate_t *a_delegate, void * a_arg); -static void s_http_proc(dap_http_simple_t *a_http_simple, void * arg ); -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_init - * @param a_domain - * @return - */ -int dap_chain_net_srv_vpn_cdb_auth_init (const char * a_domain, const char * a_mode, bool a_is_registration_open) -{ - s_is_registration_open = a_is_registration_open; - - s_domain = dap_strdup(a_domain); - - // Prefix for gdb groups - s_group_users = dap_strdup_printf("cdb.%s.users",s_domain); - s_group_serials = dap_strdup_printf("cdb.%s.serials",s_domain); - s_group_serials_activated = dap_strdup_printf("cdb.%s.serials_activated",s_domain); - - // Cookie -> login - s_group_cookies = dap_strdup_printf("cdb.%s.cookies",s_domain); - - // mode: passwd or serial - if(!dap_strcmp(a_mode, "serial")) - s_mode_passwd = false; - else if(!dap_strcmp(a_mode, "passwd")) - s_mode_passwd = true; - else{ - log_it( L_ERROR, "Unknown cdb mode=%s", a_mode); - return -1; - } - - // Login -> Password, First Name, Last Name, Email, Cookie,Timestamp Last Update, Timestamp Last Login - s_group_password = dap_strdup_printf("%s.password",s_group_users); - s_group_first_name = dap_strdup_printf("%s.first_name",s_group_users); - s_group_last_name = dap_strdup_printf("%s.last_name",s_group_users); - s_group_email = dap_strdup_printf("%s.email",s_group_users); - s_group_cookie = dap_strdup_printf("%s.cookie",s_group_users); - s_group_ts_updated = dap_strdup_printf("%s.ts_updated",s_group_users); - s_group_ts_last_login = dap_strdup_printf("%s.ts_last_login",s_group_users); - s_group_ts_active_till = dap_strdup_printf("%s.ts_active_till",s_group_users); - - return 0; -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_deinit - */ -void dap_chain_net_srv_vpn_cdb_auth_deinit() -{ -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_set_callback - * @param a_callback_success - */ -void dap_chain_net_srv_vpn_cdb_auth_set_callback(dap_enc_http_callback_t a_callback_success) -{ - s_callback_success = a_callback_success; -} - -/* - * Convert XXXXXXXXXXXXXXXX -> XXXX-XXXX-XXXX-XXXX - */ -static char* make_fullserial(const char * a_serial) -{ - if(dap_strlen(a_serial)!=16) - return dap_strdup(a_serial); - return dap_strdup_printf("%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c", - a_serial[0], a_serial[1], a_serial[2], a_serial[3], - a_serial[4], a_serial[5], a_serial[6], a_serial[7], - a_serial[8], a_serial[9], a_serial[10], a_serial[11], - a_serial[12], a_serial[13], a_serial[14], a_serial[15] - ); -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_check_password - * @param a_login - * @param a_password - * @return - */ -int dap_chain_net_srv_vpn_cdb_auth_check_login(const char * a_login, const char * a_password) -{ - int l_ret; - - size_t l_tmp_size=0; - dap_chain_hash_fast_t *l_gdb_password_hash; - if ( (l_gdb_password_hash = (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get ( - a_login,&l_tmp_size ,s_group_password ) ) ==NULL ){ - // No user in database - return -1; - } - - char * l_hash_str = dap_strdup_printf("%s%s",a_password, s_salt_str ); - dap_chain_hash_fast_t l_password_hash = {0}; - dap_hash_fast(l_hash_str,dap_strlen(l_hash_str), &l_password_hash ); - DAP_DELETE(l_hash_str); - - l_ret = (memcmp(&l_password_hash, l_gdb_password_hash,sizeof (l_password_hash) ) == 0)? 0: -2; - DAP_DELETE(l_gdb_password_hash); - - // if password check passed lets see is it active or not - if ( l_ret == 0){ - time_t *l_ts_active_till= (time_t*) dap_chain_global_db_gr_get( a_login, &l_tmp_size, s_group_ts_active_till ); - if ( l_ts_active_till ){ - if ( *l_ts_active_till < time(NULL) ) - l_ret = -4; - }else - l_ret = -3; - } - return l_ret; -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_activate_serial - * @param a_login - * @param a_password - * @return - */ -int dap_chain_net_srv_vpn_cdb_auth_activate_serial(const char * a_serial_raw, const char * a_serial, const char * a_sign, const char * a_pkey) -{ - int l_ret = -1; - if(!a_sign || !a_pkey) - return -2;//OP_CODE_LOGIN_INCORRECT_SIGN - dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(a_serial, NULL); - // not found - if(!l_serial_key) - return -1;//OP_CODE_NOT_FOUND_LOGIN_IN_DB - // already activated - if(l_serial_key->header.activated) { - l_ret = 0;// OK - } - else { - // check sign - int l_res = 0; - byte_t *l_pkey_raw = NULL; - size_t l_pkey_raw_size = 0; - { - // deserealize pkey - dap_enc_key_t *l_client_key = NULL; - size_t l_pkey_length = dap_strlen(a_pkey); - l_pkey_raw = DAP_NEW_Z_SIZE(byte_t, l_pkey_length); - memset(l_pkey_raw, 0, l_pkey_length); - l_pkey_raw_size = dap_enc_base64_decode(a_pkey, l_pkey_length, l_pkey_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); - l_client_key = dap_enc_key_new(DAP_ENC_KEY_TYPE_SIG_TESLA); - l_res = dap_enc_key_deserealize_pub_key(l_client_key, l_pkey_raw, l_pkey_raw_size); - // verify sign - if(!l_res) { - byte_t *l_sign_raw = NULL; - size_t l_sign_length = dap_strlen(a_sign); - l_sign_raw = DAP_NEW_Z_SIZE(byte_t, l_sign_length*2); - size_t l_sign_raw_size = dap_enc_base64_decode(a_sign, l_sign_length, l_sign_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); - dap_sign_t *l_sign = (dap_sign_t*)l_sign_raw;//dap_sign_pack(l_client_key, l_sign_raw, l_sign_raw_size, l_pkey_raw, l_pkey_length); - size_t as = dap_sign_get_size(l_sign); - size_t l_serial_len = dap_strlen(a_serial_raw); - l_res = dap_sign_verify(l_sign, a_serial_raw, l_serial_len); - DAP_DELETE(l_sign_raw); - } - //dap_enc_key_deserealize_sign - } - - // activate serial key - if(l_res==1) { - // added pkey to serial - l_serial_key->header.ext_size = l_pkey_raw_size; - l_serial_key = DAP_REALLOC(l_serial_key,dap_serial_key_len(l_serial_key)); - l_serial_key->header.activated = time(NULL); - memcpy(l_serial_key->ext, l_pkey_raw, l_pkey_raw_size); - // save updated serial - if(dap_chain_global_db_gr_set(dap_strdup(l_serial_key->header.serial), l_serial_key, - dap_serial_key_len(l_serial_key), - s_group_serials_activated)) { - dap_chain_global_db_gr_del(l_serial_key->header.serial, s_group_serials); - l_ret = 0;// OK - } - } - else{ - return -2;//OP_CODE_LOGIN_INCORRECT_SIGN - } - DAP_DELETE(l_pkey_raw); - } - DAP_DELETE(l_serial_key); - return l_ret; -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_check_password - * @param a_login - * @param a_password - * @return - */ -int dap_chain_net_srv_vpn_cdb_auth_check_serial(const char * a_serial, const char * a_pkey_b64) -{ - int l_ret = 0; - dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(a_serial, NULL); - // not found - if(!l_serial_key) - return -1; - // inactive serial key - if(!l_serial_key->header.activated) { - l_ret = -3; - } - // check time expired - else if(l_serial_key->header.expired) { - if((l_serial_key->header.activated + l_serial_key->header.expired) < time(NULL)) - l_ret = -4; - } - DAP_DELETE(l_serial_key); - return l_ret; -} - -/** - * @brief s_input_validation - * @param str - * @return - */ -static int s_input_validation(const char * str) -{ - // The compiler will stack "multiple" "strings" "end" "to" "end" - // into "multiplestringsendtoend", so we don't need one giant line. - static const char *nospecial="0123456789" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - ".=@?_!#$%-";// /+ - while(*str) // Loop until (*url) == 0. (*url) is about equivalent to url[0]. - { - // Can we find the character at *url in the string 'nospecial'? - // If not, it's a special character and we should return 0. - if(strchr(nospecial, *str) == NULL){ - return(0); - } - str++; // Jump to the next character. Adding one to a pointer moves it ahead one element. - } - - return(1); // Return 1 for success. -} - -/** - * Generate serial number like xxx-xxx-xxx - * without symbols 0,1,L,I,O - * a_group_sepa may be NULL - */ -static char* generate_serial(int a_group_count, int a_group_len, const char *a_group_sepa) -{ - size_t l_group_sepa_len = a_group_sepa ? strlen(a_group_sepa) : 0; - char *l_serial = DAP_NEW_Z_SIZE(char, a_group_count * (a_group_len + l_group_sepa_len)); - int l_serial_pos = 0; - for(int l_group_count = 0; l_group_count < a_group_count; l_group_count++) { - for(int l_group_len = 0; l_group_len < a_group_len; l_group_len++) { - uint32_t l_max_len = 'Z' - 'A' + 5; //['Z' - 'A' - 3]alpha + [10 - 2]digit - uint32_t l_value = random_uint32_t(l_max_len); - char l_sym; - if(l_value < 8) - l_sym = '2' + l_value; - // replace unused characters I,O,L - else if(l_value == 'I' - 'A' + 8) - l_sym = 'X'; - else if(l_value == 'L' - 'A' + 8) - l_sym = 'Y'; - else if(l_value == 'O' - 'A' + 8) - l_sym = 'Z'; - else - l_sym = 'A' + l_value - 8; - l_serial[l_serial_pos] = l_sym; - l_serial_pos++; - } - // copy separator to serial - if(l_group_sepa_len && l_group_count < a_group_count - 1) { - dap_stpcpy(l_serial + l_serial_pos, a_group_sepa); - l_serial_pos += l_group_sepa_len; - } - } - return l_serial; -} - - -size_t dap_serial_key_len(dap_serial_key_t *a_serial_key) -{ - if(!a_serial_key) - return 0; - return sizeof(dap_serial_key_t) + a_serial_key->header.ext_size; -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial - * @param a_user_str - * @param a_arg_index - * @param a_argc - * @param a_argv - * @param a_str_reply - * @param a_group_out - * @return - */ -dap_serial_key_t* dap_chain_net_srv_vpn_cdb_auth_get_serial_param(const char *a_serial_str, const char **a_group_out) -{ - const char *l_group_out = s_group_serials_activated; - if(!a_serial_str) - return NULL; - size_t l_serial_data_len = 0; - dap_serial_key_t *l_serial_key = (dap_serial_key_t*)dap_chain_global_db_gr_get(a_serial_str, &l_serial_data_len, s_group_serials_activated); - if(!l_serial_key){ - l_serial_key = (dap_serial_key_t*)dap_chain_global_db_gr_get(a_serial_str, &l_serial_data_len, s_group_serials); - l_group_out = s_group_serials; - } - if(l_serial_data_len>=sizeof(dap_serial_key_t)){ - if(a_group_out) - *a_group_out = l_group_out; - return l_serial_key; - } - DAP_DELETE(l_serial_key); - return NULL; -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial - * @param a_user_str - * @param a_arg_index - * @param a_argc - * @param a_argv - * @param a_str_reply - * @return - */ -int dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial(const char *a_serial_str, int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply) -{ - int l_ret = 0; - // Command 'serial list' - if(!dap_strcmp(a_serial_str, "list")) { - const char * l_serial_count_str = NULL; - const char * l_serial_shift_str = NULL; - int l_serial_nototal = dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-nototal", NULL); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-n", &l_serial_count_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-shift", &l_serial_shift_str); - size_t l_serial_count = l_serial_count_str ? strtoll(l_serial_count_str, NULL, 10) : 0; - size_t l_serial_shift = l_serial_shift_str ? strtoll(l_serial_shift_str, NULL, 10)+1 : 1; - size_t l_total = dap_chain_global_db_driver_count(s_group_serials, l_serial_shift); - l_serial_count = l_serial_count ? min(l_serial_count, l_total - l_serial_shift) : l_total; - dap_store_obj_t *l_obj = dap_chain_global_db_driver_cond_read(s_group_serials, l_serial_shift, &l_serial_count); - if(l_serial_count > 0) { - dap_string_t *l_keys = l_serial_count > 1 ? dap_string_new("serial keys:\n") : dap_string_new("serial key: "); - for(size_t i = 0; i < l_serial_count; i++) { - if((l_obj + i)->value_len < sizeof(dap_serial_key_t)) - continue; - dap_serial_key_t *l_serial = (dap_serial_key_t*) (l_obj + i)->value; - dap_string_append(l_keys, l_serial->header.serial); - //if(i < l_serial_count - 1) - dap_string_append(l_keys, "\n"); - } - if(!l_serial_nototal){ - char *l_total_str = dap_strdup_printf("total %u keys", l_total); - dap_string_append(l_keys, l_total_str); - DAP_DELETE(l_total_str); - //dap_chain_node_cli_set_reply_text(a_str_reply, "\ntotal %u keys", l_total); - //return 0; - } - dap_chain_node_cli_set_reply_text(a_str_reply, "%s", l_keys->str); - dap_string_free(l_keys, true); - dap_store_obj_free(l_obj, l_serial_count); - } - else - dap_chain_node_cli_set_reply_text(a_str_reply, "keys not found"); - return 0; - } - else - // Command 'serial generate' - if(!dap_strcmp(a_serial_str, "generate")) { - const char * l_serial_count_str = NULL; - const char * l_active_days_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-n", &l_serial_count_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-active_days", &l_active_days_str); - uint32_t l_serial_count = l_serial_count_str ? strtoll(l_serial_count_str, NULL, 10) : 1; - size_t l_active_days = l_active_days_str ? strtoll(l_active_days_str, NULL, 10) : 0; - if(l_serial_count < 1) - l_serial_count = 1; - dap_string_t *l_keys = l_serial_count > 1 ? dap_string_new("serial keys:\n") : dap_string_new("serial key: "); - for(uint32_t i = 0; i < l_serial_count; i++) { - dap_serial_key_t l_serial; - memset(&l_serial, 0, sizeof(dap_serial_key_t)); - while(1) { - char *l_serial_str = generate_serial(4, 4, "-"); - uint8_t *l_serial_str_prev = dap_chain_global_db_gr_get(l_serial_str, NULL, s_group_serials); - if(l_serial_str_prev) - DAP_DELETE(l_serial_str_prev); - else{ - strncpy(l_serial.header.serial, l_serial_str, sizeof(l_serial.header.serial)); - if(l_active_days) - l_serial.header.expired = l_active_days * 86400;// days to sec - break; - } - }; - l_serial.header.ext_size = 0; - - if(dap_chain_global_db_gr_set(dap_strdup(l_serial.header.serial), &l_serial, sizeof(l_serial), s_group_serials)) { - dap_string_append(l_keys, l_serial.header.serial); - if(i < l_serial_count - 1) - dap_string_append(l_keys, "\n"); - } - } - dap_chain_node_cli_set_reply_text(a_str_reply, "generated new %s", l_keys->str); - dap_string_free(l_keys, true); - // save gdb - dap_chain_global_db_flush(); - return 0; - } - else - // Command 'serial update' - if(!dap_strcmp(a_serial_str, "update")) { - const char * l_serial_number_str = NULL; - const char * l_active_days_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-serial", &l_serial_number_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-active_days", &l_active_days_str); - size_t l_active_days = l_active_days_str ? strtoll(l_active_days_str, NULL, 10) : 0; - if(!l_serial_number_str) { - dap_chain_node_cli_set_reply_text(a_str_reply, "option '-serial XXXX-XXXX-XXXX-XXXX' is not defined"); - } - else if(!l_active_days_str) { - dap_chain_node_cli_set_reply_text(a_str_reply, "option '-active_days <active days that left for serial after activation>' is not defined"); - } - else { - const char *l_group; - dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(l_serial_number_str, &l_group); - if(l_serial_key){ - l_serial_key->header.expired = l_active_days; - // save updated serial - if(dap_chain_global_db_gr_set(dap_strdup(l_serial_key->header.serial), l_serial_key, dap_serial_key_len(l_serial_key), l_group)) { - dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' successfully updated", l_serial_key->header.serial); - DAP_DELETE(l_serial_key); - // save gdb - dap_chain_global_db_flush(); - return 0; - } - else{ - dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' can't updated", l_serial_key->header.serial); - } - DAP_DELETE(l_serial_key); - } - else{ - dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' not found", l_serial_number_str); - } - return 0; - } - } - else { - dap_chain_node_cli_set_reply_text(a_str_reply, "unknown subcommand %s, use 'generate', 'list' or 'update'", a_serial_str); - } - return -1; -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_auth_cli_cmd_user - * @param a_user_str - * @param a_arg_index - * @param a_argc - * @param a_argv - * @param a_str_reply - * @return - */ -int dap_chain_net_srv_vpn_cdb_auth_cli_cmd_user(const char *a_user_str, int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply) -{ - int l_ret = 0; - dap_string_t * l_ret_str = dap_string_new(""); - // Command 'user create' - bool l_is_user_create = (dap_strcmp(a_user_str, "create") == 0 ); - bool l_is_user_update = (dap_strcmp(a_user_str, "update") == 0 ); - if ( l_is_user_create || l_is_user_update ){ - const char * l_login_str = NULL; - const char * l_password_str = NULL; - const char * l_first_name_str = NULL; - const char * l_last_name_str = NULL; - const char * l_email_str = NULL; - const char * l_active_days_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--password", &l_password_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--first_name", &l_first_name_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--last_name", &l_last_name_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--email", &l_email_str); - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--active_days", &l_active_days_str); - - if ( ( l_is_user_create && l_login_str && l_password_str ) || - ( l_is_user_update && l_login_str && ( l_password_str || l_first_name_str || l_last_name_str || l_email_str ) ) ){ - - if (l_password_str){ - char * l_hash_str = dap_strdup_printf("%s%s",l_password_str, s_salt_str ); - dap_chain_hash_fast_t *l_password_hash = DAP_NEW_Z(dap_chain_hash_fast_t); - dap_hash_fast(l_hash_str,dap_strlen(l_hash_str), l_password_hash ); - DAP_DELETE(l_hash_str); - dap_chain_global_db_gr_set(dap_strdup(l_login_str), l_password_hash,sizeof(*l_password_hash),s_group_password ); - } - - if ( l_first_name_str ) - dap_chain_global_db_gr_set(dap_strdup(l_login_str), dap_strdup(l_first_name_str),strlen(l_first_name_str)+1,s_group_first_name ); - - if ( l_last_name_str ) - dap_chain_global_db_gr_set(dap_strdup(l_login_str), dap_strdup(l_last_name_str),strlen(l_last_name_str)+1,s_group_last_name ); - - if ( l_email_str ) - dap_chain_global_db_gr_set(dap_strdup(l_login_str), dap_strdup(l_email_str),strlen(l_email_str)+1,s_group_email ); - - // Update timestamp - dap_chain_time_t *l_time = DAP_NEW_Z(dap_chain_time_t); - *l_time = dap_chain_time_now(); - dap_chain_global_db_gr_set(dap_strdup(l_login_str), l_time,sizeof (*l_time),s_group_ts_updated ); - l_time = NULL; // to prevent usage uleased memory that could be free in any moment - - if ( l_active_days_str ){ - uint64_t l_active_days = strtoull(l_active_days_str,NULL,10); - if ( l_active_days ){ - l_time = DAP_NEW_Z(dap_chain_time_t); - *l_time = dap_chain_time_now() + (dap_chain_time_t) l_active_days*86400ull; - dap_chain_global_db_gr_set(dap_strdup(l_login_str), l_time,sizeof (*l_time) ,s_group_ts_active_till ); - }else - dap_string_append_printf(l_ret_str,"WARNING: Wrong --active_time format\n"); - } - - if (l_is_user_create){ - dap_string_append_printf(l_ret_str,"OK: Created user '%s'\n",l_login_str ); - l_ret = 0; - }else if (l_is_user_update){ - dap_string_append_printf(l_ret_str,"OK: Updated user '%s'\n",l_login_str ); - l_ret = 0; - }else{ - dap_string_append_printf(l_ret_str,"OK: Unknown action success\n"); - l_ret = 0; - } - }else{ - if (l_is_user_create){ - dap_string_append_printf(l_ret_str,"ERROR: Need at least --login and --password options\n" ); - l_ret = -2; - }else if (l_is_user_update){ - dap_string_append_printf(l_ret_str,"ERROR: Need at least --login and one of next options: --password, --first_name, --last_name or --email\n" ); - l_ret = -3; - }else{ - dap_string_append_printf(l_ret_str,"ERROR: Unknown error in options\n"); - l_ret = -4; - } - } - - }else if ( dap_strcmp(a_user_str, "delete") == 0 ){ - const char * l_login_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str); - if ( l_login_str ) { - if ( dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_password ) ){ - dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_last_name ); - dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_first_name ); - dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_email ); - dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_cookie ); - - // Find if present cookie and delete it - size_t l_cookie_size = 0; - char * l_cookie = (char*) dap_chain_global_db_gr_get(l_login_str,&l_cookie_size, s_group_cookie ); - if ( l_cookie ){ - dap_chain_global_db_gr_del( l_cookie,s_group_cookies ); - log_it(L_WARNING,"Deleted user but its cookie is active in table. Deleted that but better also to close session"); - // TODO close session when cookie deleted - } - - dap_string_append_printf(l_ret_str,"OK: Deleted user '%s'\n",l_login_str ); - l_ret = 0; - }else{ - l_ret = -6; - dap_string_append_printf(l_ret_str,"ERROR: Can't find login '%s' in database\n", l_login_str ); - } - }else{ - l_ret = -5; - dap_string_append_printf(l_ret_str,"ERROR: Need --login option\n" ); - } - }else if ( dap_strcmp(a_user_str, "check") == 0 ){ - const char * l_login_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str); - const char * l_password_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--password", &l_password_str); - if ( l_login_str && l_password_str) { - int l_check = dap_chain_net_srv_vpn_cdb_auth_check_login (l_login_str, l_password_str); - if ( l_check == 0){ - dap_string_append_printf(l_ret_str,"OK: Passed password check for '%s'\n",l_login_str ); - l_ret = 0; - }else if (l_check == -1){ - l_ret = -7; - dap_string_append_printf(l_ret_str,"ERROR: Can't find login '%s' in database\n", l_login_str ); - }else if (l_check == -2){ - l_ret = -8; - dap_string_append_printf(l_ret_str,"ERROR: Wrong password for login '%s'\n", l_login_str ); - }else if (l_check == -3){ - l_ret = -10; - dap_string_append_printf(l_ret_str,"ERROR: Login '%s' is not activated\n", l_login_str ); - }else if (l_check == -4){ - l_ret = -11; - dap_string_append_printf(l_ret_str,"ERROR: Login '%s' activation is overdue\n", l_login_str ); - }else { - l_ret = -9; - dap_string_append_printf(l_ret_str,"ERROR: Unknown error in password check for login '%s'\n", l_login_str ); - } - }else{ - l_ret = -5; - dap_string_append_printf(l_ret_str,"ERROR: Need --login option\n" ); - } - }else if ( dap_strcmp(a_user_str, "show") == 0 ){ - const char * l_login_str = NULL; - dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str); - if ( l_login_str ) { - size_t l_password_hash_size=0; - dap_chain_hash_fast_t *l_password_hash; - if ( (l_password_hash = (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get ( - l_login_str,&l_password_hash_size ,s_group_password ) ) !=NULL ){ - dap_string_append_printf(l_ret_str,"OK: Find user '%s'\n",l_login_str ); - - size_t l_first_name_size=0; - char * l_first_name =(char *) dap_chain_global_db_gr_get ( l_login_str,&l_first_name_size ,s_group_first_name ) ; - if ( l_first_name ){ - dap_string_append_printf(l_ret_str,"\tFirst_name: %s\n", l_first_name); - DAP_DELETE( l_first_name ); - } - - size_t l_last_name_size=0; - char * l_last_name =(char *) dap_chain_global_db_gr_get ( l_login_str,&l_last_name_size ,s_group_last_name ) ; - if (l_last_name){ - dap_string_append_printf(l_ret_str,"\tLast_name: %s\n", l_last_name); - DAP_DELETE( l_last_name ); - } - - size_t l_email_size=0; - char * l_email =(char *) dap_chain_global_db_gr_get ( l_login_str,&l_email_size ,s_group_email ) ; - if (l_email){ - dap_string_append_printf(l_ret_str,"\tEmail: %s\n", l_email); - DAP_DELETE( l_email ); - } - - size_t l_ts_active_till_size = 0; - time_t *l_ts_active_till = (time_t*) dap_chain_global_db_gr_get(l_login_str, &l_ts_active_till_size, s_group_ts_active_till); - if(l_ts_active_till_size) { - double l_dt_days = difftime(*l_ts_active_till, time(NULL)) / 86400; - - if(l_dt_days < 1) { - if(l_dt_days < 0) - l_dt_days = 0; - dap_string_append_printf(l_ret_str, "\tActive hours: %.2lf\n", l_dt_days * 24); - } - else - dap_string_append_printf(l_ret_str, "\tActive days: %.2lf\n", l_dt_days); - DAP_DELETE(l_ts_active_till); - } - - l_ret = 0; - }else{ - l_ret = -6; - dap_string_append_printf(l_ret_str,"ERROR: Can't find login '%s' in database\n", l_login_str ); - } - }else{ - l_ret = -5; - dap_string_append_printf(l_ret_str,"ERROR: Need --login option\n" ); - } - }else if ( dap_strcmp(a_user_str, "list") == 0 ){ - size_t l_users_size = 0; - dap_global_db_obj_t* l_users = dap_chain_global_db_gr_load(s_group_password,&l_users_size); - if (l_users_size){ - dap_string_append_printf(l_ret_str,"OK: %zd users in DB\n",l_users_size); - for ( size_t i = 0; i < l_users_size; i++ ){ - dap_string_append_printf(l_ret_str,"\t%s\n",l_users[i].key); - } - dap_chain_global_db_objs_delete(l_users, l_users_size); - }else{ - dap_string_append_printf(l_ret_str,"OK: 0 users in DB\n"); - } - }else { - dap_string_append_printf(l_ret_str,"ERROR: Unknown command 'user %s'\n", a_user_str ); - l_ret = -1; - } - dap_chain_node_cli_set_reply_text( a_str_reply, l_ret_str->str ); - dap_string_free( l_ret_str, false ); - return l_ret; -} - - -void dap_chain_net_srv_vpn_cdb_auth_add_proc(dap_http_t * a_http, const char * a_url) -{ - dap_http_simple_proc_add(a_http,a_url,24000, s_http_proc); -} - -/** - * @brief s_http_proc Process auth request - * @param sh HTTP simple client instance - * @param arg Return if ok - */ -static void s_http_proc(dap_http_simple_t *a_http_simple, void * arg ) -{ - http_status_code_t * return_code = (http_status_code_t*)arg; - enc_http_delegate_t * l_delegate; - strcpy(a_http_simple->reply_mime,"application/octet-stream"); - - l_delegate = enc_http_request_decode(a_http_simple); - if(l_delegate){ - if(strcmp(l_delegate->url_path, "auth") == 0) { - s_http_enc_proc(l_delegate, arg); - } - else if(strcmp(l_delegate->url_path, "auth_key") == 0) { - s_http_enc_proc_key(l_delegate, arg); - } - else { - - if(l_delegate->url_path) - log_it(L_ERROR,"Wrong auth request %s",l_delegate->url_path); - else - log_it(L_ERROR,"Wrong auth request: nothing after / "); - - *return_code = Http_Status_BadRequest; - } - - enc_http_reply_encode(a_http_simple,l_delegate); - enc_http_delegate_delete(l_delegate); - }else{ - *return_code = Http_Status_Unauthorized; - log_it(L_WARNING,"No KeyID in the request"); - } -} - -/** - * @brief s_http_enc_proc Auth http interface - * @param a_delegate HTTP Simple client instance - * @param a_arg Pointer to bool with okay status (true if everything is ok, by default) - */ -static void s_http_enc_proc(enc_http_delegate_t *a_delegate, void * a_arg) -{ - http_status_code_t * l_return_code = (http_status_code_t*)a_arg; - - if((a_delegate->request)&&(strcmp(a_delegate->action,"POST")==0)){ - if(a_delegate->in_query==NULL){ - log_it(L_WARNING,"Empty auth action"); - *l_return_code = Http_Status_BadRequest; - return; - }else{ - if(strcmp(a_delegate->in_query,"logout")==0 ){ - if(dap_chain_global_db_gr_del(dap_strdup( a_delegate->cookie), s_group_cookies)){ - enc_http_reply_f(a_delegate, - "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" - "<return>Successfuly logouted</return>\n" - ); - *l_return_code = Http_Status_OK; - }else{ - log_it(L_NOTICE,"Logout action: cookie %s is already logouted (by timeout?)", a_delegate->cookie); - enc_http_reply_f(a_delegate, - "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" - "<err_str>No session in table</err_str>\n" - ); - *l_return_code = Http_Status_OK; - } - - }else if(strcmp(a_delegate->in_query,"login")==0 || strcmp(a_delegate->in_query,"serial")==0 ){ - char l_login[128]={0}; - char l_password[256]={0}; - char l_pkey[6001]={0};//char l_pkey[4096]={0}; - - char l_domain[64], l_domain2[64]; - - //log_it(L_DEBUG, "request_size=%d request_str='%s'\n",a_delegate->request_size, a_delegate->request_str); - - // password mode - if(s_mode_passwd) { - if(sscanf(a_delegate->request_str, "%127s %255s %63s %6000s %63s", l_login, l_password, l_domain, - l_pkey, l_domain2) >= 4 || - sscanf(a_delegate->request_str, "%127s %255s %6000s ", l_login, l_password, l_pkey) >= 3) { - log_it(L_INFO, "Trying to login with username '%s'", l_login); - - if(s_input_validation(l_login) == 0) { - log_it(L_WARNING, "Wrong symbols in username"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - return; - } - if(s_input_validation(l_password) == 0) { - log_it(L_WARNING, "Wrong symbols in password"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - return; - } - if(s_input_validation(l_pkey) == 0) { - log_it(L_WARNING, "Wrong symbols in base64 pkey string"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - return; - } - - int l_login_result = dap_chain_net_srv_vpn_cdb_auth_check_login(l_login, l_password); - switch (l_login_result) { - case 0: { - size_t l_tmp_size; - char * l_first_name = (char*) dap_chain_global_db_gr_get(l_login, &l_tmp_size, - s_group_first_name); - char * l_last_name = (char*) dap_chain_global_db_gr_get(l_login, &l_tmp_size, - s_group_last_name); - char * l_email = (char*) dap_chain_global_db_gr_get(l_login, &l_tmp_size, s_group_email); - dap_chain_time_t * l_ts_last_logined = (dap_chain_time_t*) dap_chain_global_db_gr_get( - l_login, &l_tmp_size, s_group_ts_last_login); - dap_chain_time_t *l_ts_active_till = (dap_chain_time_t*) dap_chain_global_db_gr_get(l_login, - &l_tmp_size, s_group_ts_active_till); - - enc_http_reply_f(a_delegate, - "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" - "<auth_info>\n" - ); - enc_http_reply_f(a_delegate, "\t<login>%s</login>\n", l_login); - if(l_first_name) - enc_http_reply_f(a_delegate, "\t<first_name>%s</first_name>\n", l_first_name); - if(l_last_name) - enc_http_reply_f(a_delegate, "\t<last_name>%s</last_name>\n", l_last_name); - if(l_email) - enc_http_reply_f(a_delegate, "\t<email>%s</email>\n", l_email); - if(l_ts_last_logined) - enc_http_reply_f(a_delegate, "\t<ts_prev_login>%llu</ts_prev_login>\n", (long long unsigned) *l_ts_last_logined); - if(l_ts_active_till) - enc_http_reply_f(a_delegate, "\t<ts_active_till>%llu</ts_acyive_till>\n", (long long unsigned) *l_ts_active_till); - - if(a_delegate->cookie) - enc_http_reply_f(a_delegate, "\t<cookie>%s</cookie>\n", a_delegate->cookie); - dap_chain_net_srv_vpn_cdb_auth_after(a_delegate, l_login, l_pkey); // Here if smbd want to add smth to the output - enc_http_reply_f(a_delegate, "</auth_info>"); - log_it(L_INFO, "Login: Successfuly logined user %s", l_login); - *l_return_code = Http_Status_OK; - //log_it(L_DEBUG, "response_size='%d'",a_delegate->response_size); - DAP_DELETE(l_first_name); - DAP_DELETE(l_last_name); - DAP_DELETE(l_email); - DAP_DELETE(l_ts_last_logined); - DAP_DELETE(l_ts_active_till); - - // Update last logined - l_ts_last_logined = DAP_NEW_Z(dap_chain_time_t); - *l_ts_last_logined = dap_chain_time_now(); - dap_chain_global_db_gr_set(dap_strdup(l_login), l_ts_last_logined, sizeof(time_t), s_group_ts_last_login); - DAP_DELETE(l_ts_last_logined); - } - break; - case -1: - enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB); - *l_return_code = Http_Status_OK; - break; - case -2: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_PSWD); - *l_return_code = Http_Status_OK; - break; - case -3: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INACTIVE); - *l_return_code = Http_Status_OK; - break; - case -4: - enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED); - *l_return_code = Http_Status_PaymentRequired; - break; - default: - log_it(L_WARNING, "Login: Unknown authorize error for login '%s'", l_login); - *l_return_code = Http_Status_BadRequest; - break; - } - } else { - log_it(L_DEBUG, "Login: wrong auth's request body "); - *l_return_code = Http_Status_BadRequest; - } - } - // serial mode - else - { - char l_serial_tmp[64]={0}; - if(sscanf(a_delegate->request_str, "%63s %63s %6000s", l_serial_tmp, l_domain, l_pkey) >= 3) { - char *l_serial = make_fullserial(l_serial_tmp); - log_it(L_INFO, "Trying to login with serial '%s'", l_serial); - if(s_input_validation(l_serial) == 0) { - log_it(L_WARNING, "Wrong symbols in serial"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - DAP_DELETE(l_serial); - return; - } - if(s_input_validation(l_domain) == 0) { - log_it(L_WARNING, "Wrong symbols in l_domain"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - DAP_DELETE(l_serial); - return; - } - if(s_input_validation(l_pkey) == 0) { - log_it(L_WARNING, "Wrong symbols in base64 pkey string"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - DAP_DELETE(l_serial); - return; - } - int l_login_result = dap_chain_net_srv_vpn_cdb_auth_check_serial(l_serial, l_pkey); - log_it(L_INFO, "Check serial '%s' with code %d (Ok=0)", l_serial, l_login_result); - switch (l_login_result) { - case 0: { - size_t l_tmp_size; - enc_http_reply_f(a_delegate, - "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" - "<auth_info>\n" - ); - enc_http_reply_f(a_delegate, "\t<serial>%s</serial>\n", l_serial); - - dap_chain_time_t * l_ts_last_logined = (dap_chain_time_t*) dap_chain_global_db_gr_get(l_serial, &l_tmp_size, s_group_ts_last_login); - dap_chain_time_t *l_ts_active_till = (dap_chain_time_t*) dap_chain_global_db_gr_get(l_serial, &l_tmp_size, s_group_ts_active_till); - if(l_ts_last_logined) - enc_http_reply_f(a_delegate, "\t<ts_prev_login>%llu</ts_prev_login>\n", (long long unsigned) *l_ts_last_logined); - if(l_ts_active_till) - enc_http_reply_f(a_delegate, "\t<ts_active_till>%llu</ts_acyive_till>\n", (long long unsigned) *l_ts_active_till); - if(a_delegate->cookie) - enc_http_reply_f(a_delegate, "\t<cookie>%s</cookie>\n", a_delegate->cookie); - dap_chain_net_srv_vpn_cdb_auth_after(a_delegate, l_serial, l_pkey); // Here if smbd want to add smth to the output - enc_http_reply_f(a_delegate, "</auth_info>"); - log_it(L_INFO, "Login: Successfuly logined user %s", l_login); - *l_return_code = Http_Status_OK; - //log_it(L_DEBUG, "response_size='%d'",a_delegate->response_size); - - DAP_DELETE(l_ts_last_logined); - DAP_DELETE(l_ts_active_till); - - // Update last logined - l_ts_last_logined = DAP_NEW_Z(dap_chain_time_t); - *l_ts_last_logined = dap_chain_time_now(); - dap_chain_global_db_gr_set(dap_strdup(l_serial), l_ts_last_logined, sizeof(time_t),s_group_ts_last_login); - DAP_DELETE(l_ts_last_logined); - } - break; - case -1: - enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB); - *l_return_code = Http_Status_OK; - break; - /*case -2: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_PSWD); - *l_return_code = Http_Status_OK; - break;*/ - case -3: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INACTIVE); - *l_return_code = Http_Status_OK; - break; - case -4: - enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED); - *l_return_code = Http_Status_PaymentRequired; - break; - default: - log_it(L_WARNING, "Login: Unknown authorize error for login '%s'", l_login); - *l_return_code = Http_Status_BadRequest; - break; - } - DAP_DELETE(l_serial); - } - } - }else if (s_is_registration_open && strcmp(a_delegate->in_query,"register")==0){ - char l_login[128]; - char l_password[256]; - char l_first_name[128]; - char l_last_name[128]; - char l_email[256]; - - log_it(L_INFO, "Request str = %s", a_delegate->request_str); - if(sscanf(a_delegate->request_str,"%127s %255s %127s %127s %255s" - ,l_login,l_password,l_email,l_first_name,l_last_name)>=3){ - if(s_input_validation(l_login)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the username '%s'",l_login); - *l_return_code = Http_Status_BadRequest; - return; - } - if(s_input_validation(l_password)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the password"); - *l_return_code = Http_Status_BadRequest; - return; - } - if(s_input_validation(l_first_name)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the first name '%s'",l_first_name); - *l_return_code = Http_Status_BadRequest; - return; - } - if(s_input_validation(l_last_name)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the last name '%s'",l_last_name); - *l_return_code = Http_Status_BadRequest; - return; - } - if(s_input_validation(l_email)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the email '%s'",l_email); - *l_return_code = Http_Status_BadRequest; - return; - } - if ( l_login[0] && l_password[0] && l_email[0] ){ - - // Hash password with salt - char * l_hash_str = dap_strdup_printf("%s%s",l_password, s_salt_str ); - dap_chain_hash_fast_t *l_password_hash = DAP_NEW_Z(dap_chain_hash_fast_t); - dap_hash_fast(l_hash_str,dap_strlen(l_hash_str), l_password_hash ); - DAP_DELETE(l_hash_str); - dap_chain_global_db_gr_set(dap_strdup(l_login), l_password_hash,sizeof(*l_password_hash),s_group_password ); - - // Write email in db - dap_chain_global_db_gr_set(dap_strdup(l_login), dap_strdup(l_email),strlen(l_email)+1,s_group_email ); - - enc_http_reply_f(a_delegate, - "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" - "<auth_info>\n" - ); - - enc_http_reply_f(a_delegate,"\t<login>%s</login>\n",l_login); - // Write first and last names in db if present - if ( l_first_name[0] ){ - dap_chain_global_db_gr_set( dap_strdup(l_login), dap_strdup(l_first_name),strlen(l_first_name)+1, - s_group_first_name ); - enc_http_reply_f(a_delegate,"\t<first_name>%s</first_name>\n",l_first_name); - } - - if ( l_last_name[0] ){ - dap_chain_global_db_gr_set( dap_strdup(l_login), dap_strdup( l_last_name ), strlen( l_last_name)+1, - s_group_last_name ); - enc_http_reply_f(a_delegate,"\t<last_name>%s</last_name>\n",l_last_name); - } - - // If cookie present - report it - if ( a_delegate->cookie ) - enc_http_reply_f(a_delegate,"\t<cookie>%s</cookie>\n",a_delegate->cookie ); - enc_http_reply_f(a_delegate,"</auth_info>"); - - log_it(L_NOTICE,"Registration: new user %s \"%s %s\"<%s> is registred",l_login,l_first_name,l_last_name,l_email); - } - }else{ - log_it(L_ERROR, "Registration: Wrong auth's request body "); - *l_return_code = Http_Status_BadRequest; - } - }else{ - log_it(L_ERROR, "Unknown auth command was selected (query_string='%s')",a_delegate->in_query); - *l_return_code = Http_Status_BadRequest; - } - } - }else{ - log_it(L_ERROR, "Wrong auth request action '%s'",a_delegate->action); - *l_return_code = Http_Status_BadRequest; - } -} - -/** - * @brief s_http_enc_proc Auth http interface - * @param a_delegate HTTP Simple client instance - * @param a_arg Pointer to bool with okay status (true if everything is ok, by default) - */ -static void s_http_enc_proc_key(enc_http_delegate_t *a_delegate, void * a_arg) -{ - http_status_code_t * l_return_code = (http_status_code_t*) a_arg; - - if((a_delegate->request) && (strcmp(a_delegate->action, "POST") == 0)) { - if(a_delegate->in_query == NULL) { - log_it(L_WARNING, "Empty auth action"); - *l_return_code = Http_Status_BadRequest; - return; - } else { - if(strcmp(a_delegate->in_query, "serial") == 0) { - char l_serial_raw[64] = { 0 }; - char l_serial_sign[12000] = { 0 }; - char l_pkey[6001] = { 0 }; - - // only for serial mode - if(!s_mode_passwd) - { - char l_domain[64]; - if(sscanf(a_delegate->request_str, "%63s %12000s %63s %6000s", l_serial_raw, l_serial_sign, l_domain, l_pkey) >= 4) { - char *l_serial = make_fullserial(l_serial_raw); - /*size_t a1 = dap_strlen(l_serial); - size_t a2 = dap_strlen(l_serial_sign); - size_t a3 = dap_strlen(l_pkey);*/ - log_it(L_INFO, "Trying to activate with serial '%s'", l_serial); - if(s_input_validation(l_serial) == 0) { - log_it(L_WARNING, "Wrong symbols in serial"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - DAP_DELETE(l_serial); - return; - } - if(s_input_validation(l_pkey) == 0) { - log_it(L_WARNING, "Wrong symbols in base64 pkey string"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - DAP_DELETE(l_serial); - return; - } - if(s_input_validation(l_serial_sign) == 0) { - log_it(L_WARNING, "Wrong symbols in base64 serial sign"); - enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS); - *l_return_code = Http_Status_BadRequest; - DAP_DELETE(l_serial); - return; - } - int l_activate_result = dap_chain_net_srv_vpn_cdb_auth_activate_serial(l_serial_raw, l_serial, l_serial_sign, l_pkey); - log_it(L_INFO, "Serial '%s' activated with code %d (Ok=0)", l_serial, l_activate_result); - switch (l_activate_result) { - case 0: - enc_http_reply_f(a_delegate, OP_CODE_SERIAL_ACTIVED); - *l_return_code = Http_Status_OK; - break; - case -1: - enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB); - *l_return_code = Http_Status_OK; - break; - case -2: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_SIGN); - *l_return_code = Http_Status_OK; - break; - /*case -3: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INACTIVE); - *l_return_code = Http_Status_OK; - break;*/ - case -4: - enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED); - *l_return_code = Http_Status_PaymentRequired; - break; - default: - log_it(L_WARNING, "Login: Unknown authorize error for activate serial '%s'", l_serial); - *l_return_code = Http_Status_BadRequest; - break; - } - DAP_DELETE(l_serial); - } - else { - log_it(L_ERROR, "Registration: Wrong auth_key's request body "); - *l_return_code = Http_Status_BadRequest; - } - } - } else { - log_it(L_ERROR, "Unknown auth command was selected (query_string='%s')", a_delegate->in_query); - *l_return_code = Http_Status_BadRequest; - } - } - } else { - log_it(L_ERROR, "Wrong auth request action '%s'", a_delegate->action); - *l_return_code = Http_Status_BadRequest; - } -} diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c deleted file mode 100644 index b03956319f890a8f994e5de51b97f28eb3508e52..0000000000000000000000000000000000000000 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * Alexander Lysikov <alexander.lysikov@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * CellFrame https://cellframe.net - * Sources https://gitlab.demlabs.net/cellframe - * Copyright (c) 2017-2019 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <time.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - - -#include "dap_common.h" -#include "dap_config.h" - -#include "dap_chain.h" -#include "dap_chain_net.h" -#include "dap_chain_net_srv.h" -#include "dap_chain_net_srv_vpn.h" -#include "dap_chain_net_srv_order.h" -#include "dap_chain_net_srv_geoip.h" - -#include "dap_http.h" -#include "dap_http_simple.h" -#include "http_status_code.h" - -#include "dap_chain_net_srv_vpn_cdb_server_list.h" - -#define LOG_TAG "dap_chain_net_srv_vpn_cdb_server_list" - - -static size_t s_cdb_net_count = 0; -static dap_chain_net_t ** s_cdb_net = NULL; -static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg); - -int dap_chain_net_srv_vpn_cdb_server_list_init() -{ - char **l_cdb_networks; - uint16_t l_cdb_networks_count = 0; - log_it(L_NOTICE,"Initialized Server List Module"); - l_cdb_networks = dap_config_get_array_str( g_config, "cdb", "servers_list_networks", &l_cdb_networks_count ); - - if ( l_cdb_networks_count ){ - s_cdb_net = DAP_NEW_Z_SIZE(dap_chain_net_t*, sizeof (dap_chain_net_t*)* l_cdb_networks_count ); - s_cdb_net_count = l_cdb_networks_count; - for ( size_t i = 0; i < l_cdb_networks_count ; i++) { - s_cdb_net[i] = dap_chain_net_by_name( l_cdb_networks[i] ); - if ( s_cdb_net[i] ) - log_it( L_INFO, "Added \"%s\" network for server list fetchs", l_cdb_networks[i]); - else - log_it( L_WARNING, "Can't find \"%s\" network to add to server list fetchs", l_cdb_networks[i]); - } - } else - log_it( L_WARNING, "No chain networks listed in config"); - - return 0; -} - -void dap_chain_net_srv_vpn_cdb_server_list_deinit(void) -{ -} - - -/** - * @brief order_info_print - * @param a_server_location for server name, NULL not used - * @param a_node_number for server name, <0 not use - */ -static int order_info_print(dap_string_t *a_reply_str, dap_chain_net_t * a_net, dap_chain_net_srv_order_t * a_order, const char *a_server_name, int a_node_number) -{ - dap_chain_node_info_t * l_node_info = dap_chain_node_info_read(a_net, &a_order->node_addr); - if(l_node_info) { - char l_node_ext_ipv4_str[INET_ADDRSTRLEN] = { 0 }; - char l_node_ext_ipv6_str[INET6_ADDRSTRLEN] = { 0 }; - if(l_node_info->hdr.ext_addr_v4.s_addr) - inet_ntop(AF_INET, &l_node_info->hdr.ext_addr_v4, l_node_ext_ipv4_str, sizeof(l_node_ext_ipv4_str)); - if(*((uint128_t *) l_node_info->hdr.ext_addr_v6.s6_addr)) - inet_ntop(AF_INET6, &l_node_info->hdr.ext_addr_v6, l_node_ext_ipv6_str, sizeof(l_node_ext_ipv6_str)); - - uint8_t l_continent_num = 0; - char *l_region = NULL; - dap_chain_net_srv_order_get_continent_region(a_order, &l_continent_num, &l_region); - const char *l_continent_str = dap_chain_net_srv_order_continent_to_str(l_continent_num); - // ext_out in hex view - char *l_ext_out = a_order->ext_size ? DAP_NEW_Z_SIZE(char, a_order->ext_size * 2 + 1) : NULL; - dap_bin2hex(l_ext_out, a_order->ext, a_order->ext_size); - - dap_string_append_printf(a_reply_str, " {\n"); - dap_string_append_printf(a_reply_str, " \"Location\":\"%s\",\n", l_region ? l_region : "None"); //NETHERLANDS - //l_continent_str ? l_continent_str : "None", l_region ? l_region : "None"); - - - dap_string_append_printf(a_reply_str, " \"ChainNet\":\"%s\",\n", a_net->pub.name); - //dap_string_append_printf(a_reply_str, " \"Name\":\"%s.Cell-%lu.%zd\",\n", a_net->pub.name, l_node_info->hdr.cell_id.uint64, 0); - if(a_server_name) - dap_string_append_printf(a_reply_str, " \"Name\":\"%s\",\n", a_server_name); - else - dap_string_append_printf(a_reply_str, " \"Name\":\"%s.%s.%zd\",\n", l_continent_str ? l_continent_str : "", l_region ? l_region : "", a_node_number + 1); - //dap_string_append_printf(a_reply_str, " \"Name\":\"%s.%s.Cell-%lu.%zd\",\n", l_continent_str ? l_continent_str : "", l_region ? l_region : "", l_node_info->hdr.cell_id.uint64, a_node_number + 1); - if(l_node_ext_ipv4_str[0]) - dap_string_append_printf(a_reply_str, " \"Address\":\"%s\",\n", l_node_ext_ipv4_str); - if(l_node_ext_ipv6_str[0]) - dap_string_append_printf(a_reply_str, " \"Address6\":\"%s\",\n", l_node_ext_ipv6_str); - dap_string_append_printf(a_reply_str, " \"Port\":%hu,\n", l_node_info->hdr.ext_port ? l_node_info->hdr.ext_port : 80); - - //dap_string_append_printf(a_reply_str, " \"Ext\":\"%s-%s\",\n", l_continent_str ? l_continent_str : "", l_region ? l_region : ""); - if(l_ext_out) - dap_string_append_printf(a_reply_str, " \"Ext\":\"0x%s\",\n", l_ext_out); - else - dap_string_append_printf(a_reply_str, " \"Ext\":\"0x0\",\n"); - dap_string_append_printf(a_reply_str, " \"Price\":%lu,\n", a_order->price); - dap_string_append_printf(a_reply_str, " \"PriceUnits\":%u,\n", a_order->price_unit.uint32); - dap_string_append_printf(a_reply_str, " \"PriceToken\":\"%s\"\n", a_order->price_ticker); - dap_string_append_printf(a_reply_str, " }"); - DAP_DELETE(l_region); - DAP_DELETE(l_ext_out); - - - } else{ - log_it(L_WARNING, "Order in \"%s\" network issued by node without ext_ipv4 field", a_net->pub.name); - return -1; - } - return 0; -} - - -static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg) -{ - http_status_code_t * l_ret_code = (http_status_code_t*)a_arg; - dap_string_t *l_reply_str = dap_string_new("[\n"); - - - char *l_client_ip = a_http_simple->http->client->s_ip;//"64.225.61.216" - geoip_info_t *l_geoip_info = chain_net_geoip_get_ip_info(l_client_ip); - - log_it(L_DEBUG, "Have %zd chain networks for cdb lists", s_cdb_net_count ); - - for ( size_t i = 0; i < s_cdb_net_count ; i++ ) { - dap_chain_net_t * l_net = s_cdb_net[i]; - if ( l_net ) { - dap_chain_net_srv_order_t * l_orders = NULL; - size_t l_orders_num = 0; - dap_chain_net_srv_price_unit_uid_t l_unit_uid = {{0}}; - dap_chain_net_srv_uid_t l_srv_uid = { .uint64 =DAP_CHAIN_NET_SRV_VPN_ID }; - dap_chain_net_srv_order_find_all_by( l_net, SERV_DIR_SELL, l_srv_uid, l_unit_uid , - NULL,0,0, &l_orders, &l_orders_num ); - log_it(L_DEBUG, "Found %zd orders in \"%s\" network", l_orders_num, l_net->pub.name ); - - - // find the shift for each node - dap_chain_net_srv_order_t *l_orders_pos[l_orders_num]; - size_t l_orders_size = 0; - for(size_t j = 0; j < l_orders_num; j++) { - l_orders_pos[j] = (dap_chain_net_srv_order_t*) ((char*) l_orders + l_orders_size); - l_orders_size += dap_chain_net_srv_order_get_size(l_orders_pos[j]); - } - - - // list of node numbers - size_t l_continents_count = dap_chain_net_srv_order_continents_count(); //int *l_node_numbering = DAP_NEW_Z_SIZE(int, l_orders_num * sizeof(int)); - // list of the number of nodes in each continent - int l_continents_numbers[l_continents_count]; //int *l_continents_numbers = DAP_NEW_Z_SIZE(int, l_continents_count * sizeof(int)); - int l_node_numbering[l_continents_count][l_orders_num]; - // init arrays - for(size_t m1 = 0; m1 < l_continents_count; m1++) { - l_continents_numbers[m1] = 0; - for(size_t m2 = 0; m2 < l_orders_num; m2++) - l_node_numbering[m1][m2] = -1; - } - - // node numbering - size_t l_orders_used_num = 0; - { - // filling l_continents_numbers and l_node_numbering - for(size_t j = 0; j < l_orders_num; j++) { - dap_chain_net_srv_order_t *l_order = l_orders_pos[j]; - uint8_t l_continent_num; - if(!dap_chain_net_srv_order_get_continent_region(l_order, &l_continent_num, NULL)) - continue; - l_node_numbering[l_continent_num][j] = l_continents_numbers[l_continent_num]++; - l_orders_used_num++; - } - // shuffle nodes for each continent - for(size_t m1 = 0; m1 < l_continents_count; m1++) { - int l_cont_num = l_continents_numbers[m1]; - if(l_cont_num <= 1) - continue; - // number of shuffles - int l_shuffle_num = rand() % (l_cont_num + 1); - for(size_t l_sh = 0; l_sh <= l_shuffle_num; l_sh++) { - size_t l_pos1 = 0; - size_t l_pos2 = 0; - while(l_pos1 == l_pos2) { - l_pos1 = rand() % l_cont_num; - l_pos2 = rand() % l_cont_num; - } - for(size_t m2 = 0; m2 < l_orders_num; m2++) { - if(l_node_numbering[m1][m2] == l_pos1) - l_node_numbering[m1][m2] = l_pos2; - else if(l_node_numbering[m1][m2] == l_pos2) - l_node_numbering[m1][m2] = l_pos1; - } - } - } - } - - int8_t l_client_continent = l_geoip_info ? dap_chain_net_srv_order_continent_to_num(l_geoip_info->continent) : 0; - // random node on client's continent - if(l_client_continent > 0 && l_continents_numbers[l_client_continent] > 1) { - int l_count = 0; - while(l_orders_num > 0) { - size_t k = rand() % l_continents_numbers[l_client_continent]; - size_t l_node_pos = -1; - for(size_t j2 = 0; j2 <= l_orders_num; j2++) { - if(k == l_node_numbering[l_client_continent][j2]) { - l_node_pos = j2; - break; - } - } - if(l_node_pos == -1) { - // random node for the whole world - l_node_pos = rand() % l_orders_num; - } - dap_chain_net_srv_order_t *l_order = l_orders_pos[l_node_pos]; - const char *country_code = dap_chain_net_srv_order_get_country_code(l_order); - if(country_code) { - // only for other countries - if(dap_strcmp(l_geoip_info->country_code, country_code)) { - if(!order_info_print(l_reply_str, l_net, l_order, "Auto", -1)) { - dap_string_append_printf(l_reply_str, ",\n"); - break; - } - } - } - if(l_count > 20) - break; - l_count++; - } - - } - // random node for the whole world - else { - int l_count = 0; - while(l_orders_num > 0) { - // first random node - size_t k = rand() % l_orders_num; - dap_chain_net_srv_order_t *l_order = l_orders_pos[k]; - if(!order_info_print(l_reply_str, l_net, l_order, "Auto", -1)){ - dap_string_append_printf(l_reply_str, ",\n"); - break; - } - if (l_count>20) - break; - l_count++; - } - } - // random nodes for continents - int l_count = 0; - for(size_t l_c = 0; l_c < l_continents_count; l_c++) { - while(l_continents_numbers[l_c] > 0) { - // random node for continent - size_t k = rand() % l_continents_numbers[l_c]; - size_t l_node_pos = -1; - for(size_t j2 = 0; j2 <= l_orders_num; j2++) { - if(k == l_node_numbering[l_c][j2]) { - l_node_pos = j2; - break; - } - } - if(l_node_pos == -1) - break; - dap_chain_net_srv_order_t *l_order = l_orders_pos[l_node_pos]; - char *l_server_name = dap_strdup_printf("%s", dap_chain_net_srv_order_continent_to_str(l_c)); - if(!order_info_print(l_reply_str, l_net, l_order, l_server_name, -1)) { - dap_string_append_printf(l_reply_str, ",\n"); - DAP_DELETE(l_server_name); - break; - } - else - DAP_DELETE(l_server_name); - if(l_count > 20) - break; - l_count++; - } - } - - for(size_t l_c = 0; l_c < l_continents_count; l_c++) { - // print all nodes for continent - for(size_t l_n = 0; l_n < l_continents_numbers[l_c]; l_n++) { - // since the nodes are shuffled, look for the desired node index - for(size_t l_o = 0; l_o < l_orders_num; l_o++) { - if(l_node_numbering[l_c][l_o] != l_n) - continue; - dap_chain_net_srv_order_t *l_order = l_orders_pos[l_o]; - if(!order_info_print(l_reply_str, l_net, l_order, NULL, l_n)) { - dap_string_append_printf(l_reply_str, ",\n"); - } - break; - } - } - } - } - } - DAP_DELETE(l_geoip_info); - //delete trailing comma if exists - if(l_reply_str->str[l_reply_str->len - 2] == ','){ - dap_string_truncate(l_reply_str, l_reply_str->len - 2); - dap_string_append_printf(l_reply_str, "\n"); - } - - dap_string_append_printf( l_reply_str, "]\n\n"); - dap_http_simple_reply( a_http_simple, l_reply_str->str, l_reply_str->len ); - dap_string_free(l_reply_str, true); - //log_it(L_DEBUG,"Reply in buffer: %s", a_http_simple->reply_str ); - *l_ret_code = Http_Status_OK; - -} - -/** - * @brief dap_chain_net_srv_vpn_cdb_server_list_add_proc - * @param sh - * @param url - */ -void dap_chain_net_srv_vpn_cdb_server_list_add_proc(dap_http_t *a_http, const char *a_url) -{ - dap_http_simple_proc_add(a_http,a_url,100000,s_http_simple_proc); -} diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..01a18e9f0d56708000f00ff5ed3d7baefd032d39 --- /dev/null +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c @@ -0,0 +1,170 @@ +#include <dap_chain_node_cli.h> +#include "dap_chain_node_cli_cmd.h" +#include "dap_chain_net_srv_vpn_cmd.h" +#include "dap_chain_net_vpn_client.h" + +/** + * vpn_client command + * + * VPN client control + */ +int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) +{ +#ifndef _WIN32 + enum { + CMD_NONE, CMD_INIT, CMD_START, CMD_STOP, CMD_STATUS + }; + int l_arg_index = 1; + // find net + dap_chain_net_t *l_net = NULL; + if(dap_chain_node_cli_cmd_values_parse_net_chain(&l_arg_index, a_argc, a_argv, a_str_reply, NULL, &l_net) < 0) + return -2; + + int cmd_num = CMD_NONE; + if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "init", NULL)) { + cmd_num = CMD_INIT; + } + if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "start", NULL)) { + cmd_num = CMD_START; + } + else if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "stop", NULL)) { + cmd_num = CMD_STOP; + } + else if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "status", NULL)) { + cmd_num = CMD_STATUS; + } + if(cmd_num == CMD_NONE) { + if(!a_argv[1]) + dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameters"); + else + dap_chain_node_cli_set_reply_text(a_str_reply, "parameter %s not recognized", a_argv[1]); + return -1; + } + + switch (cmd_num) + { + case CMD_INIT: { + const char * l_str_token = NULL; // token name + const char * l_str_value_datoshi = NULL; + const char * l_str_wallet = NULL; // wallet name + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_str_wallet); + if(!l_str_wallet) + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_str_wallet); + + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-token", &l_str_token); + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_str_value_datoshi); + + if(!l_str_wallet) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Wallet not defined, use -w <wallet_name> or -wallet <wallet_name> parameter"); + break; + } + if(!l_str_token) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Token not defined, use -token <token_name> parameter"); + break; + } + if(!l_str_value_datoshi) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Value of datoshi not defined, use -value <value of datoshi> parameter"); + break; + } + uint64_t l_a_value_datoshi = strtoull(l_str_value_datoshi, NULL, 10); + if(!l_a_value_datoshi) + l_a_value_datoshi = strtoull(l_str_value_datoshi, NULL, 16); + if(!l_a_value_datoshi) { + dap_chain_node_cli_set_reply_text(a_str_reply, "Value of datoshi have to be more then 0"); + break; + } + int l_res = dap_chain_net_vpn_client_update(l_net, l_str_wallet, l_str_token, l_a_value_datoshi); + if(!l_res) + dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client init successfully"); + else{ + if(l_res==-3) + dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client init successfully, but probably not enough founds in the wallet"); + else + dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client not init"); + } + return l_res; + } + break; + case CMD_START: { + const char * l_str_addr = NULL; // for example, "192.168.100.93" + const char * l_str_port = NULL; // for example, "8079" + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr", &l_str_addr); + if(!l_str_addr) { + dap_chain_node_cli_set_reply_text(a_str_reply, + "VPN server address not defined, use -addr <vpn server ipv4 address> parameter"); + break; + } + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-port", &l_str_port); + int l_srv_port = (l_str_port) ? (int) strtoll(l_str_port, 0, 10) : 0; + if(!l_srv_port) { + dap_chain_node_cli_set_reply_text(a_str_reply, + "VPN server port not defined, use -port <vpn server port> parameter"); + break; + } + int l_res = dap_chain_net_vpn_client_start(l_net, l_str_addr, NULL, l_srv_port); + switch (l_res) { + case 0: + dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client started successfully"); + break; + case 1: + dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client already started"); + break; + case -2: + case -3: + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't connect to VPN server"); + break; + default: + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't start VPN client"); + break; + } + return l_res; + } + break; + case CMD_STOP: { + int res = dap_chain_net_vpn_client_stop(); + if(!res) + dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client stopped successfully"); + else + dap_chain_node_cli_set_reply_text(a_str_reply, "VPN client not stopped"); + return res; + } + break; + case CMD_STATUS: + { + char *l_wallet_name = NULL, *l_str_token = NULL; + uint64_t l_value_datoshi = 0; + dap_chain_net_vpn_client_get_wallet_info(l_net, &l_wallet_name, &l_str_token, &l_value_datoshi); + + const char *l_status_txt = ""; + switch (dap_chain_net_vpn_client_status()) { + case VPN_CLIENT_STATUS_NOT_STARTED: + l_status_txt = "VPN client not started"; + break; + case VPN_CLIENT_STATUS_STARTED: + l_status_txt = "VPN client started"; + break; + case VPN_CLIENT_STATUS_STOPPED: + l_status_txt = "VPN client stopped"; + break; + case VPN_CLIENT_STATUS_CONN_LOST: + l_status_txt = "VPN client lost connection"; + break; + default: + l_status_txt = "VPN client status unknown"; + break; + } + dap_chain_node_cli_set_reply_text(a_str_reply, "%s\nused:\nwallet:%s\nreceipt:%u*1e-9 %s", l_status_txt, + l_wallet_name, l_value_datoshi, l_str_token); + break; + } + } +#endif + return 0; +} + + +int dap_chain_net_srv_vpn_cmd_init() +{ + + +} diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h new file mode 100644 index 0000000000000000000000000000000000000000..4ce2243e8703bc14aa9ead66b5120f38562e8b00 --- /dev/null +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.h @@ -0,0 +1,4 @@ +#pragma once + +// vpn_client command +int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply); diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c index 7a673697cd20befce5711f09121ff087912dafa0..9109e9320c28d6a7b677901982c23649be93ca4c 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client.c +++ b/modules/service/vpn/dap_chain_net_vpn_client.c @@ -55,6 +55,7 @@ #include "dap_stream_ch_chain_net_srv.h" //#include "dap_stream_ch_chain_net_srv.h" #include "dap_chain_net_vpn_client_tun.h" +#include "dap_chain_net_srv_vpn_cmd.h" //#include "dap_chain_net_vpn_client_data.h" /* @@ -724,6 +725,12 @@ void dap_chain_net_vpn_client_pkt_out(dap_stream_ch_t* a_ch) int dap_chain_net_vpn_client_init(dap_config_t * g_config) { pthread_mutex_init(&sf_socks_mutex, NULL); + + // vpn client command + dap_chain_node_cli_cmd_item_create ("vpn_client", com_vpn_client, NULL, "VPN client control", + "vpn_client [start -addr <server address> -port <server port>| stop | status] -net <net name>\n"); + + return dap_chain_net_srv_client_vpn_init(g_config); } diff --git a/modules/service/vpn/include/dap_chain_net_srv_vpn_cdb_auth.h b/modules/service/vpn/include/dap_chain_net_srv_vpn_cdb_auth.h index 8682421039c334431ef333fc981e9b2e10e9e31a..820d9f81936a8ada6244ff6706c28434aeba1003 100644 --- a/modules/service/vpn/include/dap_chain_net_srv_vpn_cdb_auth.h +++ b/modules/service/vpn/include/dap_chain_net_srv_vpn_cdb_auth.h @@ -31,11 +31,15 @@ typedef struct dap_serial_key { struct { char serial[20]; time_t activated; // if set, then serial is activated - time_t expired; // if zero then time no expired - int32_t os;// operating system. if zero then any operating system + // if zero then time no expired + union{ + time_t expired; + int64_t license_length;// in sec + }; + int32_t pkey_type;// dap_enc_key_type_t pkey type size_t ext_size; }DAP_ALIGN_PACKED header; - uint8_t ext[]; + uint8_t ext[];// pkey here }DAP_ALIGN_PACKED dap_serial_key_t; size_t dap_serial_key_len(dap_serial_key_t *a_serial_key); @@ -46,7 +50,7 @@ void dap_chain_net_srv_vpn_cdb_auth_deinit(); void dap_chain_net_srv_vpn_cdb_auth_add_proc(dap_http_t * a_http, const char * a_url); void dap_chain_net_srv_vpn_cdb_auth_set_callback(dap_enc_http_callback_t a_callback_success); -int dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial(const char *a_user_str, int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply); +int dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial(const char *a_serial_str, int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply); int dap_chain_net_srv_vpn_cdb_auth_cli_cmd_user(const char *a_user_str, int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply); int dap_chain_net_srv_vpn_cdb_auth_check_login(const char * a_login, const char * a_password); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 20c03c5db409e62f1be0674124252bfda888695f..b7bd5071492e047932395300fca186099c49d41c 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -87,6 +87,8 @@ int dap_chain_net_srv_xchange_init() void dap_chain_net_srv_xchange_deinit() { + if(!s_srv_xchange) + return; dap_chain_net_srv_xchange_price_t *l_price = NULL, *l_tmp; HASH_ITER(hh, s_srv_xchange->pricelist, l_price, l_tmp) { HASH_DEL(s_srv_xchange->pricelist, l_price); diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 3d76887d71005e5f28bd56e7187fe25d45d2855c..48afa1e8855c846f51d948e5d11639dd6acde486 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -77,8 +77,8 @@ typedef struct dap_chain_cs_dag_pvt { #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt ) // Atomic element organization callbacks -static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t ); // Accept new event in dag -static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t ); // Verify new event in dag +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t ); // Accept new event in dag +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t ); // Verify new event in dag static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t ); // Get dag event size static size_t s_chain_callback_atom_get_static_hdr_size(void); // Get dag event header size @@ -281,14 +281,29 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger } static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t * a_dag, dap_ledger_t * a_ledger, dap_chain_cs_dag_event_item_t * a_event_item ){ - HASH_ADD(hh, PVT(a_dag)->events,hash,sizeof (a_event_item->hash), a_event_item); - s_dag_events_lasts_process_new_last_event(a_dag, a_event_item); - int res = a_dag->callback_cs_verify(a_dag,a_event_item->event); - if(res == 0) + if(res == 0){ res = s_dap_chain_add_atom_to_ledger(a_dag, a_ledger, a_event_item); + HASH_ADD(hh, PVT(a_dag)->events,hash,sizeof (a_event_item->hash), a_event_item); + s_dag_events_lasts_process_new_last_event(a_dag, a_event_item); + } + + return res; +} + +static bool s_dap_chain_check_if_event_is_present(dap_chain_cs_dag_event_item_t * a_hash_table, const dap_chain_hash_fast_t * hash){ + bool res = false; + dap_chain_cs_dag_event_item_t * l_event_search = NULL; + + if(!a_hash_table) + return false; + + HASH_FIND(hh, a_hash_table, hash, sizeof(*hash), l_event_search); + if ( l_event_search ) + res = true; + return res; } @@ -298,51 +313,62 @@ static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t * a_dag, dap_ * @param a_atom * @return 0 if verified and added well, otherwise if not */ -static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) { - bool l_add_to_threshold = false; - int ret = s_chain_callback_atom_verify (a_chain, a_atom); - if ( ret < 0 ){ - log_it(L_WARNING,"Wrong event, can't accept, verification returned %d",ret); - return -1; - }else if( ret > 0){ - l_add_to_threshold = true; - } - + dap_chain_atom_verify_res_t ret = ATOM_ACCEPT; dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain); dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom; dap_chain_cs_dag_event_item_t * l_event_item = DAP_NEW_Z(dap_chain_cs_dag_event_item_t); + pthread_rwlock_t * l_events_rwlock = &PVT(l_dag)->events_rwlock ; l_event_item->event = l_event; l_event_item->ts_added = time(NULL); + dap_hash_fast(l_event, dap_chain_cs_dag_event_calc_size(l_event),&l_event_item->hash ); + dap_chain_hash_fast_t l_event_hash; + dap_chain_cs_dag_event_calc_hash(l_event,&l_event_hash); + + char * l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash); + log_it(L_DEBUG, "Processing event: %s...", l_event_hash_str); - // Put in main table or in the treshhold if not all the rest linked event are present - dap_chain_cs_dag_event_item_t * l_event_search = NULL; - dap_chain_cs_dag_event_item_t * l_events =( l_add_to_threshold )? PVT(l_dag)->events_treshold : PVT(l_dag)->events ; - pthread_rwlock_t * l_events_rwlock = &PVT(l_dag)->events_rwlock ; pthread_rwlock_wrlock( l_events_rwlock ); - HASH_FIND(hh, l_events,&l_event_item->hash,sizeof (l_event_search->hash), l_event_search); - if ( l_event_search ) { - pthread_rwlock_unlock( l_events_rwlock ); - char * l_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash); - log_it(L_ERROR, "Dag event %s is already present in dag",l_hash_str); - DAP_DELETE(l_event_item); - DAP_DELETE(l_hash_str); - return -3; + + // check if we already have this event + if(s_dap_chain_check_if_event_is_present(PVT(l_dag)->events, &l_event_item->hash)){ + ret = ATOM_PASS; + log_it(L_DEBUG, "... already present in events"); + }else if(s_dap_chain_check_if_event_is_present(PVT(l_dag)->events_treshold, &l_event_item->hash)){ + ret = ATOM_PASS; + log_it(L_DEBUG, "... already present in threshold"); } - int res = 0; - if(l_add_to_threshold){ + // verify hashes and consensus + if(ret == ATOM_ACCEPT) + ret = s_chain_callback_atom_verify (a_chain, a_atom); + + if( ret == ATOM_MOVE_TO_THRESHOLD){ HASH_ADD(hh, PVT(l_dag)->events_treshold,hash,sizeof (l_event_item->hash), l_event_item); - }else{ - res = s_dap_chain_add_atom_to_events_table(l_dag, a_chain->ledger, l_event_item); + log_it(L_DEBUG, "... added to threshold"); + }else if( ret == ATOM_ACCEPT){ + int l_consensus_check = s_dap_chain_add_atom_to_events_table(l_dag, a_chain->ledger, l_event_item); + if(!l_consensus_check){ + log_it(L_DEBUG, "... added"); + }else{ + log_it(L_DEBUG, "... error adding"); + ret = ATOM_REJECT; + } } while(dap_chain_cs_dag_proc_treshold(l_dag, a_chain->ledger)); pthread_rwlock_unlock( l_events_rwlock ); - return res; + if(ret == ATOM_PASS){ + DAP_DELETE(l_event_item); + } + + DAP_DELETE(l_event_hash_str); + + return ret; } /** @@ -542,14 +568,16 @@ dap_chain_cs_dag_event_t* dap_chain_cs_dag_find_event_by_hash(dap_chain_cs_dag_t * @param a_atom * @return */ -static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) { dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain); dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom; + dap_chain_atom_verify_res_t res = ATOM_ACCEPT; + + // genesis or seed mode if (l_event->header.hash_count == 0){ if(s_seed_mode && !PVT(l_dag)->events) - //starting a new network and this is a genesis event - return 0; + return ATOM_ACCEPT; if (l_dag->is_static_genesis_event ){ dap_chain_hash_fast_t l_event_hash; @@ -561,36 +589,37 @@ static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_pt log_it(L_WARNING, "Wrong genesis block %s (staticly predefined %s)",l_event_hash_str, l_genesis_event_hash_str); DAP_DELETE(l_event_hash_str); DAP_DELETE(l_genesis_event_hash_str); - return -22; + return ATOM_REJECT; + }else{ + return ATOM_ACCEPT; } - return 0; } } - int ret = l_dag->callback_cs_verify ( l_dag, l_event ); - if (ret == 0 ){ - if ( PVT(l_dag)->events ){ - for (size_t i = 0; i< l_event->header.hash_count; i++) { - dap_chain_hash_fast_t * l_hash = ((dap_chain_hash_fast_t *) l_event->hashes_n_datum_n_signs) + i; - dap_chain_cs_dag_event_item_t * l_event_search = NULL; - HASH_FIND(hh, PVT(l_dag)->events ,l_hash ,sizeof (*l_hash), l_event_search); - if ( l_event_search == NULL ){ - char * l_hash_str = dap_chain_hash_fast_to_str_new(l_hash); - log_it(L_DEBUG, "Hash %s wasn't in hashtable of previously parsed", l_hash_str); - DAP_DELETE(l_hash_str); - return 1; - } + //chain coherence + if (! PVT(l_dag)->events ){ + res = ATOM_MOVE_TO_THRESHOLD; + }else{ + for (size_t i = 0; i< l_event->header.hash_count; i++) { + dap_chain_hash_fast_t * l_hash = ((dap_chain_hash_fast_t *) l_event->hashes_n_datum_n_signs) + i; + dap_chain_cs_dag_event_item_t * l_event_search = NULL; + HASH_FIND(hh, PVT(l_dag)->events ,l_hash ,sizeof (*l_hash), l_event_search); + if ( l_event_search == NULL ){ + char * l_hash_str = dap_chain_hash_fast_to_str_new(l_hash); + log_it(L_INFO, "Hash %s wasn't in hashtable of previously parsed", l_hash_str); + DAP_DELETE(l_hash_str); + res = ATOM_MOVE_TO_THRESHOLD; + break; } - return 0; - }else{ - //event looks fine but we have no hash table yet and can't verify it's hashes - //so it goes into threshold - return 1; } - - }else { - return ret; } + + //consensus + if(res == ATOM_ACCEPT) + if(l_dag->callback_cs_verify ( l_dag, l_event )) + res = ATOM_REJECT; + + return res; } /** @@ -698,7 +727,17 @@ bool dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag, dap_ledger_t * a HASH_DEL(PVT(a_dag)->events_treshold,l_event_item); if(ret == DAP_THRESHOLD_OK){ - s_dap_chain_add_atom_to_events_table(a_dag, a_ledger, l_event_item); + char * l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash); + log_it(L_DEBUG, "Processing event (threshold): %s...", l_event_hash_str); + + int l_add_res = s_dap_chain_add_atom_to_events_table(a_dag, a_ledger, l_event_item); + if(! l_add_res){ + log_it(L_DEBUG, "... added", l_event_hash_str); + }else{ + log_it(L_DEBUG, "... error adding", l_event_hash_str); + //todo: delete event + } + DAP_DELETE(l_event_hash_str); res = true; }else if(ret == DAP_THRESHOLD_CONFLICTING) HASH_ADD(hh, PVT(a_dag)->events_treshold_conflicted, hash,sizeof (l_event_item->hash), l_event_item); diff --git a/modules_dynamic/CMakeLists.txt b/modules_dynamic/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f4c99055a84659c988d3da1e5da165433129084e --- /dev/null +++ b/modules_dynamic/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(cdb) + diff --git a/modules_dynamic/cdb/CMakeLists.txt b/modules_dynamic/cdb/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a53e016eb7276048420e90c215c72ee992acd1da --- /dev/null +++ b/modules_dynamic/cdb/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8) +project (dap_modules_dynamic_cdb) + +file(GLOB DAP_MODULES_DYNAMIC_CDB_SRCS *.c) + +file(GLOB DAP_MODULES_DYNAMIC_CDB_HEADERS include/*.h) + +add_library(${PROJECT_NAME} STATIC ${DAP_MODULES_DYNAMIC_CDB_SRCS} ${DAP_MODULES_DYNAMIC_CDB_HEADERS}) + +#target_link_libraries(dap_chain_net_srv dap_core dap_crypto dap_chain dap_chain_net dap_chain_wallet) +target_link_libraries(${PROJECT_NAME} dap_core dap_http_server ${CMAKE_DL_LIBS}) + +target_include_directories(${PROJECT_NAME} INTERFACE .) +target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/modules_dynamic/cdb/dap_modules_dynamic_cdb.c b/modules_dynamic/cdb/dap_modules_dynamic_cdb.c new file mode 100644 index 0000000000000000000000000000000000000000..696838cbeb2a120d60ea81bdf9bacc4daa3d0cf9 --- /dev/null +++ b/modules_dynamic/cdb/dap_modules_dynamic_cdb.c @@ -0,0 +1,69 @@ +/* + * Authors: + * Aleksei I. Voronin <aleksei.voronin@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2017-2019 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dap_modules_dynamic_cdb.h" +#include "dap_common.h" + +#ifdef DAP_OS_LINUX +#include <dlfcn.h> +#endif + +#define LOG_TAG "dap_http" + +static const char * s_default_path_modules = "var/modules"; + +int dap_modules_dynamic_load_cdb(dap_http_t * a_server){ + char l_lib_path[MAX_PATH] = {'\0'}; +#if defined (DAP_OS_LINUX) && !defined (__ANDROID__) + const char * l_cdb_so_name = "libcellframe-node-cdb.so"; + dap_sprintf(l_lib_path, "%s/%s/%s", g_sys_dir_path, s_default_path_modules, l_cdb_so_name); + + void* l_cdb_handle = NULL; + l_cdb_handle = dlopen(l_lib_path, RTLD_NOW); + if(!l_cdb_handle){ + log_it(L_ERROR,"Can't load %s module: %s", l_cdb_so_name, dlerror()); + return -1; + } + + int (*dap_chain_net_srv_vpn_cdb_init)(dap_http_t*); + const char * l_init_func_name = "dap_chain_net_srv_vpn_cdb_init"; + *(void **) (&dap_chain_net_srv_vpn_cdb_init) = dlsym(l_cdb_handle, l_init_func_name); + char* error; + if (( error = dlerror()) != NULL) { + log_it(L_ERROR,"%s module: %s error loading %s (%s)", l_cdb_so_name, l_init_func_name, error); + return -2; + } + + int l_init_res = (*dap_chain_net_srv_vpn_cdb_init)(a_server); + if(l_init_res){ + log_it(L_ERROR,"%s: %s returns %d", l_cdb_so_name, l_init_func_name, error); + return -3; + } + + return 0; +#else + log_it(L_ERROR,"%s: module is not supported on current platfrom", __PRETTY_FUNCTION__); + return -3; +#endif +} diff --git a/modules_dynamic/cdb/include/dap_modules_dynamic_cdb.h b/modules_dynamic/cdb/include/dap_modules_dynamic_cdb.h new file mode 100644 index 0000000000000000000000000000000000000000..492b98c71127b030ed44527e276fa41eeda9d9e1 --- /dev/null +++ b/modules_dynamic/cdb/include/dap_modules_dynamic_cdb.h @@ -0,0 +1,29 @@ +/* + * Authors: + * Aleksei I. Voronin <aleksei.voronin@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2017-2019 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once +#include "dap_http.h" + +int dap_modules_dynamic_load_cdb(dap_http_t * a_server); +