diff --git a/CMakeLists.txt b/CMakeLists.txt index 8207a6ef3da2dff7d46bba8d12f55bac6561cd0a..fbb209f0818137f563ea6641d9354b769df4710c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,9 +33,6 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRV_VPN_SRCS} ${DAP_CHAIN_NET target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_net dap_chain_net_srv) -if(NOT ANDROID) - target_link_libraries(${PROJECT_NAME} dap_server_http_db_auth dap_server_http_db) -endif() target_include_directories(${PROJECT_NAME} INTERFACE .) diff --git a/dap_chain_net_srv_vpn_cdb.c b/dap_chain_net_srv_vpn_cdb.c index 525837b7350fae0658257be78a4efd60c14a2e14..fbb51b4a804e162668809a262c2527ceed1fd963 100644 --- a/dap_chain_net_srv_vpn_cdb.c +++ b/dap_chain_net_srv_vpn_cdb.c @@ -29,13 +29,6 @@ #include "dap_enc_base64.h" #include "dap_http.h" -#ifndef __ANDROID__ -#include "db_core.h" -#include "db_auth.h" -#include "db_http.h" -#include "db_http_file.h" -#endif - #include "dap_chain.h" #include "dap_chain_net.h" #include "dap_chain_ledger.h" @@ -50,19 +43,21 @@ #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 DB_FILE_URL "/db_file" -#define SLIST_URL "/nodelist" +#define NODELIST_URL "/nodelist" typedef struct tx_cond_template{ char * wallet_name; @@ -82,7 +77,7 @@ typedef struct tx_cond_template{ static tx_cond_template_t *s_tx_cond_templates = NULL; const char *c_wallets_path = NULL; -static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg); +static int s_cli_vpn_cdb(int a_argc, char ** a_argv, char **a_str_reply); /** * @brief dap_chain_net_srv_vpn_cdb_init @@ -90,7 +85,6 @@ static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg); */ int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http) { - int rc; int ret=0; c_wallets_path = dap_chain_wallet_get_path(g_config); if (dap_config_get_item_bool_default( g_config, @@ -104,26 +98,38 @@ int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http) } } - - if((rc=db_core_init(dap_config_get_item_str_default(g_config, - "cdb", - "db_path", - "mongodb://localhost/db")))!=0 ){ - log_it(L_CRITICAL,"Can't init CDB module, return code %d",rc); - return -3; - } - db_http_add_proc( a_http , DB_URL ); - db_http_file_proc_add( a_http , DB_FILE_URL ); + dap_chain_node_cli_cmd_item_create ("vpn_cdb", s_cli_vpn_cdb , "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>]" + "[--acive_days <Setup active day thats 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" + ); // 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, SLIST_URL); + 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) ){ - db_auth_init( dap_config_get_item_str_default(g_config,"cdb_auth","collection_name","cdb") ); + + dap_chain_net_srv_vpn_cdb_auth_init( dap_config_get_item_str_default(g_config,"cdb_auth","domain","cdb"), + dap_config_get_item_bool_default(g_config,"cdb_auth","registration_open",false) + ); + 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", @@ -140,7 +146,6 @@ int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http) log_it( L_ERROR, "No condition tpl, can't setup auth callback"); return -5; } - db_auth_set_callbacks(s_auth_callback); 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); @@ -211,6 +216,24 @@ int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http) return ret; } + +static int s_cli_vpn_cdb(int a_argc, char ** a_argv, char **a_str_reply) +{ + const char *l_user_str = NULL; + int l_arg_index = 1; + int l_ret = 0; + + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "user", &l_user_str); + + + // Selected 'user' subcoummand + if ( l_user_str ){ + return dap_chain_net_srv_vpn_cdb_auth_cli_cmd(l_user_str,l_arg_index, a_argc, a_argv,a_str_reply); + } + return l_ret; +} + + /** * @brief dap_chain_net_srv_vpn_cdb_deinit */ @@ -219,28 +242,26 @@ void dap_chain_net_srv_vpn_cdb_deinit() } - - /** - * @brief s_auth_callback + * @brief dap_chain_net_srv_vpn_cdb_auth_after * @param a_delegate - * @param a_arg + * @param a_login + * @param a_pkey_b64 */ -static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg) +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__ - db_auth_info_t *l_auth_info = (db_auth_info_t *) a_arg; dap_enc_key_t *l_client_key; log_it( L_DEBUG, "Authorized, now need to create conditioned transaction if not present"); { - size_t l_pkey_b64_length = strlen(l_auth_info->pkey); - byte_t l_pkey_raw[l_pkey_b64_length]; + size_t l_pkey_b64_length = dap_strlen( a_pkey_b64); + byte_t *l_pkey_raw = DAP_NEW_Z_SIZE(byte_t,l_pkey_b64_length); memset(l_pkey_raw, 0, l_pkey_b64_length); size_t l_pkey_raw_size = - dap_enc_base64_decode(l_auth_info->pkey, l_pkey_b64_length, l_pkey_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); + 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( "%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(l_auth_info->user, l_pkey_raw, l_pkey_raw_size, 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_deserealize(l_pkey_raw, l_pkey_raw_size); DAP_DELETE(l_pkey_gdb_group); } @@ -253,7 +274,7 @@ static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg) 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); log_it(L_DEBUG, "Checkout group %s", l_tx_cond_gdb_group); dap_chain_hash_fast_t *l_tx_cond_hash = - (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get(l_auth_info->user, &l_gdb_group_size, l_tx_cond_gdb_group); + (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get(a_login, &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)) { @@ -296,7 +317,7 @@ static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg) log_it(L_ERROR, "Can't create condiftion for user"); } else { log_it(L_NOTICE, "User \"%s\": created conditioned transaction from %s(%s) on " - , l_auth_info->user, l_tpl->wallet_name, l_addr_from_str); + , a_login, l_tpl->wallet_name, l_addr_from_str); } DAP_DELETE( l_addr_from_str ); } diff --git a/dap_chain_net_srv_vpn_cdb.h b/dap_chain_net_srv_vpn_cdb.h index dc0c5842a7ef94d59614df0771ba9c09a0201fa8..4370d18b9122542fcaa680b2e7894164e4875769 100644 --- a/dap_chain_net_srv_vpn_cdb.h +++ b/dap_chain_net_srv_vpn_cdb.h @@ -24,8 +24,10 @@ */ #pragma once #include "dap_http.h" +#include "dap_enc_http.h" #define DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX "local.srv.vpn" int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http); void dap_chain_net_srv_vpn_cdb_deinit(); +void dap_chain_net_srv_vpn_cdb_auth_after(enc_http_delegate_t* a_delegate, const char * a_login, const char * a_pkey_b64 ); diff --git a/dap_chain_net_srv_vpn_cdb_auth.c b/dap_chain_net_srv_vpn_cdb_auth.c index 445ba81d8c95c5e9666510092661f1120cf5c022..0a634efaeb829330b08605e83a35ac37eb3d8787 100644 --- a/dap_chain_net_srv_vpn_cdb_auth.c +++ b/dap_chain_net_srv_vpn_cdb_auth.c @@ -23,11 +23,6 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. */ -#include "dap_common.h" -#include "dap_chain_net_srv_vpn_cdb_auth.h" - -#define LOG_TAG "dap_chain_net_srv_vpn_cdb_auth" - #include <string.h> #include <stdlib.h> @@ -38,890 +33,388 @@ #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 "db_core.h" -#include "db_auth.h" -#include "http_status_code.h" -#include "SimpleFIPS202.h" +#include "dap_chain_node_cli.h" +#include "dap_chain_global_db.h" +#include "http_status_code.h" -#define LOG_TAG "db_auth" +#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_NOT_FOUND_LOGIN_IN_DB "0xf3" #define OP_CODE_SUBSCRIBE_EXPIRIED "0xf4" #define OP_CODE_INCORRECT_SYMOLS "0xf6" -static db_auth_info_t *s_auths = NULL; -static pthread_mutex_t s_mutex_on_auth_hash = PTHREAD_MUTEX_INITIALIZER; - -static const char *s_db_name = NULL; dap_enc_http_callback_t s_callback_success = NULL; -/** - * @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; -} +static char * s_domain = NULL; +static char * s_group_users = 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_salt_str = "Ijg24GAS56h3hg7hj245b"; +static bool s_is_registration_open = false; +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_proc(dap_http_simple_t *a_http_simple, void * arg ); /** - * @brief s_auth_info_by_cookie Find user by its cookie - * @param cookie Cookie - * @return Zero if this cookie is not present + * @brief dap_chain_net_srv_vpn_cdb_auth_init + * @param a_domain + * @return */ -db_auth_info_t* s_info_by_cookie(const char * cookie) -{ - db_auth_info_t * ret = NULL; - - if ( cookie == NULL ) - { - log_it(L_ERROR, "cookie is NULL in db_auth_info_by_cookie"); - return NULL; - } - pthread_mutex_lock(&s_mutex_on_auth_hash); - HASH_FIND_STR(s_auths, cookie, ret); - pthread_mutex_unlock(&s_mutex_on_auth_hash); - if(ret == NULL) - log_it(L_NOTICE,"Cookie '%s' not present in the table",cookie); - else - log_it(L_INFO,"Cookie '%s' has been found in the table",cookie); - return ret; -} - -db_auth_info_t* db_search_cookie_in_db(const char * cookie) +int dap_chain_net_srv_vpn_cdb_auth_init (const char * a_domain, bool a_is_registration_open) { + s_is_registration_open = a_is_registration_open; - mongoc_collection_t* collection_cookie = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_cookie_history"); - - bson_t *query = bson_new(); - - BSON_APPEND_UTF8 (query, "cookie", cookie); - - mongoc_cursor_t *cursor_dap_cookie = mongoc_collection_find - (collection_cookie, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - - bson_t *doc_dap_cookie_user; - - if( mongoc_cursor_next (cursor_dap_cookie, (const bson_t**)&doc_dap_cookie_user) == false ) - { - log_it(L_INFO, "Cookie not find in database"); - return NULL; - } - - bson_iter_t iter; - - if ( !(bson_iter_init (&iter, doc_dap_cookie_user) && bson_iter_find (&iter, "login")) ) - { - log_it(L_ERROR, "Login not found in document"); - return NULL; - } - - mongoc_collection_destroy(collection_cookie); - mongoc_cursor_destroy(cursor_dap_cookie); + s_domain = dap_strdup(a_domain); - if(doc_dap_cookie_user) - bson_destroy(doc_dap_cookie_user); + // Prefix for gdb groups + s_group_users = dap_strdup_printf("cdb.%s.users",s_domain); - if(query) - bson_destroy(query); + // Cookie -> login + s_group_cookies = dap_strdup_printf("cdb.%s.cookies",s_domain); + // 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); - /* ok user find now get information */ - mongoc_collection_t* collection_dap_users = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_users"); - - query = bson_new(); - - BSON_APPEND_UTF8 (query, "login", bson_iter_value(&iter)->value.v_utf8.str); - - mongoc_cursor_t* cursor_dap_users = mongoc_collection_find - (collection_dap_users, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - - - if( mongoc_cursor_next (cursor_dap_users, (const bson_t**)&doc_dap_cookie_user) == false ) - { - log_it(L_INFO, "User not find in database"); - return NULL; - } - // mongoc_collection_destroy(collection_cookie); - - bson_iter_t sub_iter; - - // ok cookie find, get user information; - db_auth_info_t * ai = DAP_NEW_Z(db_auth_info_t); - - if (bson_iter_init (&iter, doc_dap_cookie_user) && - bson_iter_find_descendant (&iter, "profile.first_name", &sub_iter)) - { - strncpy(ai->first_name, bson_iter_value(&sub_iter)->value.v_utf8.str, - bson_iter_value(&sub_iter)->value.v_utf8.len); - } - - if (bson_iter_init (&iter, doc_dap_cookie_user) && - bson_iter_find_descendant (&iter, "profile.last_name", &sub_iter)) - { - strncpy(ai->last_name,bson_iter_value(&sub_iter)->value.v_utf8.str, - bson_iter_value(&sub_iter)->value.v_utf8.len); - } - - if (bson_iter_init (&iter, doc_dap_cookie_user) && - bson_iter_find_descendant (&iter, "profile.email", &sub_iter)) - { - strncpy(ai->email,bson_iter_value(&sub_iter)->value.v_utf8.str, - bson_iter_value(&sub_iter)->value.v_utf8.len); - } - - strcpy(ai->cookie, cookie); - - mongoc_collection_destroy(collection_dap_users); - mongoc_cursor_destroy(cursor_dap_users); - - if(doc_dap_cookie_user) - bson_destroy(doc_dap_cookie_user); - - if(query) - bson_destroy(query); - - pthread_mutex_lock(&s_mutex_on_auth_hash); - HASH_ADD_STR(s_auths,cookie,ai); - pthread_mutex_unlock(&s_mutex_on_auth_hash); - - return ai; + return 0; } /** - * @brief db_auth_user_change_password - * @param user - * @param password - * @param new_password - * @return - * @details change password for user ( check correctly current pass, for change to new ) + * @brief dap_chain_net_srv_vpn_cdb_auth_deinit */ -bool db_auth_user_change_password(const char* user, const char* password, - const char* new_password) +void dap_chain_net_srv_vpn_cdb_auth_deinit() { - if ( check_user_password(user, password) == false ) - { - log_it(L_WARNING, "Error change password. Old user password not correct" , user); - return false; - } - - return db_auth_change_password(user, new_password); } /** - * @brief db_auth_user_change_password - * @param user - * @param password - * @param new_password - * @return - * @details change passwd without check correct old password ( for admins ) + * @brief dap_chain_net_srv_vpn_cdb_auth_set_callback + * @param a_callback_success */ -bool db_auth_change_password(const char* user, const char* new_password) +void dap_chain_net_srv_vpn_cdb_auth_set_callback(dap_enc_http_callback_t a_callback_success) { - if ( exist_user_in_db(user) == false ) - { - log_it(L_WARNING, "Error change password. User %s not find" , user); - return false; - } - - mongoc_collection_t *collection_dap_users = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_users"); - - bson_t *query = bson_new(); - - BSON_APPEND_UTF8 (query, "login", user); - - mongoc_cursor_t *cursor_dap_users = mongoc_collection_find - (collection_dap_users, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - - bson_t *doc_dap_user; - - mongoc_cursor_next (cursor_dap_users, (const bson_t**)&doc_dap_user); - - bson_error_t error; - - - - char * password_hash_b64 = dap_server_db_hash_password_b64(new_password); - - if (password_hash_b64 == NULL) { - log_it(L_WARNING,"Bad hash(based64) for user password"); - return false; - } - - bson_t *update = BCON_NEW ("$set", "{", - "passwordHash", BCON_UTF8 (password_hash_b64), - "}"); - - if (!mongoc_collection_update (collection_dap_users, MONGOC_UPDATE_NONE, doc_dap_user, update, NULL, &error)) { - log_it(L_WARNING,"%s", error.message); - return false; - } - - mongoc_collection_destroy(collection_dap_users); - - if(query) - bson_destroy(query); - - if(cursor_dap_users) - mongoc_cursor_destroy(cursor_dap_users); - - if(doc_dap_user) - bson_destroy(doc_dap_user); - - DAP_DELETE( password_hash_b64 ); - - log_it(L_INFO, "user: %s change password to %s", user, new_password); - return true; + s_callback_success = a_callback_success; } - /** - * @brief db_auth_set_field_str - * @param a_user - * @param a_field_name - * @param a_field_value + * @brief dap_chain_net_srv_vpn_cdb_auth_check_password + * @param a_login + * @param a_password * @return */ -bool db_auth_set_field_str(const char* a_user, const char* a_field_name, const char * a_field_value) +int dap_chain_net_srv_vpn_cdb_auth_check_password(const char * a_login, const char * a_password) { - if ( exist_user_in_db(a_user) == false ) - { - log_it(L_WARNING, "Error set field str. User %s not find" , a_user); - return false; - } - - mongoc_collection_t *l_collection_dap_users = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_cookie_history"); - - bson_t *l_query = bson_new(); - - BSON_APPEND_UTF8 (l_query, "login", a_user); - - mongoc_cursor_t *l_cursor_dap_users = mongoc_collection_find - (l_collection_dap_users, MONGOC_QUERY_NONE, 0, 0, 0, l_query, NULL, NULL); + int l_ret; - bson_t *l_doc_dap_user; - - mongoc_cursor_next (l_cursor_dap_users, (const bson_t**)&l_doc_dap_user); - - bson_error_t l_error; - - bson_t *l_update = BCON_NEW ("$set", "{", - a_field_name, BCON_UTF8 (a_field_value), - "}"); - - if (!mongoc_collection_update (l_collection_dap_users, MONGOC_UPDATE_NONE, l_doc_dap_user, l_update, NULL, &l_error)) { - log_it(L_WARNING,"%s", l_error.message); - return false; + size_t l_gdb_password_hash_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_gdb_password_hash_size ,s_group_password ) ) ==NULL ){ + // No user in database + return -1; } - mongoc_collection_destroy(l_collection_dap_users); - - if(l_query) - bson_destroy(l_query); + 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,strlen(l_hash_str), &l_password_hash ); + DAP_DELETE(l_hash_str); - if(l_cursor_dap_users) - mongoc_cursor_destroy(l_cursor_dap_users); - - if(l_doc_dap_user) - bson_destroy(l_doc_dap_user); - - log_it(L_INFO, "set field \"%s\" with string \"%s\"", a_field_name, a_field_value ); - return true; + l_ret = (memcmp(&l_password_hash, l_gdb_password_hash,sizeof (l_password_hash) ) == 0)? 0: -2; + DAP_DELETE(l_gdb_password_hash); + return l_ret; } - /** - * @brief check_user_password - * @param user - * @param password - * @return false if user password not correct + * @brief s_input_validation + * @param str + * @return */ -bool check_user_password(const char* a_user, const char* a_password) -{ - if ( exist_user_in_db(a_user) == false ){ - log_it(L_WARNING,"User %s is not present in DB",a_user); - return false; - } - - bool is_correct_password = false; - - mongoc_collection_t *collection = mongoc_client_get_collection ( - mongo_client, s_db_name, "dap_users"); - - bson_t *query = bson_new(); - BSON_APPEND_UTF8 (query, "login", a_user); - - bson_iter_t iter; - bson_t *doc; - - mongoc_cursor_t *cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, - (const bson_t*)query, NULL, NULL); - - mongoc_cursor_next (cursor, (const bson_t**)&doc); - char salt[16] = {0}; char salt_from_b64[8] = {0}; - - if ( bson_iter_init (&iter, doc) && bson_iter_find (&iter, "salt") ) - memcpy(salt,bson_iter_value(&iter)->value.v_utf8.str,16); - else { - log_it(L_ERROR, "Not find Salt in user"); return NULL; - } - - dap_enc_base64_decode(salt, 16, salt_from_b64,DAP_ENC_DATA_TYPE_B64); - - char* l_password_hash_b64 = dap_server_db_hash_password_b64(a_password); - - if (!l_password_hash_b64) { - log_it(L_ERROR, "Can not memmory allocate"); - return NULL; - } - - if (bson_iter_init (&iter, doc) && bson_iter_find (&iter, "passwordHash")) - { - if ( memcmp(l_password_hash_b64, bson_iter_value(&iter)->value.v_utf8.str, - DB_AUTH_HASH_LENGTH * 2) == 0 ) - is_correct_password = true; - } - - mongoc_collection_destroy(collection); - - if(cursor) - mongoc_cursor_destroy(cursor); - - if(query) - bson_destroy(query); - - if(doc) - bson_destroy(doc); - - DAP_DELETE( l_password_hash_b64 ); - - return is_correct_password; -} - - -static bool s_save_cookie_inform_in_db(const char* login, db_auth_info_t * a_auth_info) +static int s_input_validation(const char * str) { - bool result = true; - mongoc_collection_t *collection = mongoc_client_get_collection ( - mongo_client, s_db_name, "dap_cookie_history"); - - bson_error_t error; - - bson_t *query = bson_new(); - BSON_APPEND_UTF8 (query, "login", login); - - mongoc_cursor_t *cursor_dap_cookie_history = mongoc_collection_find - (collection, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - - struct tm *utc_date_time; - time_t t = time(NULL); - utc_date_time = localtime(&t); - - bson_t *doc_dap_cookie; bson_t *bson_doc = NULL; - if ( mongoc_cursor_next (cursor_dap_cookie_history, (const bson_t**)&doc_dap_cookie) ) - { - bson_doc = BCON_NEW ("$set", "{", - "login", BCON_UTF8 (login), - "cookie", BCON_UTF8 (a_auth_info->cookie), - "pkey", BCON_UTF8 (a_auth_info->pkey), - "last_use", BCON_DATE_TIME(mktime (utc_date_time) * 1000), - "}"); - - if (!mongoc_collection_update (collection, MONGOC_UPDATE_UPSERT, doc_dap_cookie, bson_doc, NULL, &error)) { - log_it(L_WARNING,"%s", error.message); - result = false; - } - } - else - { - bson_doc = BCON_NEW("login", BCON_UTF8 (login), - "cookie", BCON_UTF8 (a_auth_info->cookie), - "pkey", BCON_UTF8 (a_auth_info->pkey), - "last_use", BCON_DATE_TIME(mktime (utc_date_time) * 1000)); - - if (!mongoc_collection_insert (collection, MONGOC_INSERT_NONE, bson_doc, NULL, &error)) + // 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]. { - log_it (L_WARNING, "%s\n", error.message); - result = false; + // 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. } - } - mongoc_collection_destroy(collection); - mongoc_cursor_destroy(cursor_dap_cookie_history); - bson_destroy(query); - if(doc_dap_cookie) - bson_destroy(doc_dap_cookie); - if(bson_doc) - bson_destroy(bson_doc); - - return result; + return(1); // Return 1 for success. } - /** - * @brief dap_server_db_hash_password - * @param password + * @brief dap_chain_net_srv_vpn_cdb_auth_cli_cmd + * @param a_user_str + * @param a_arg_index + * @param a_argc + * @param a_argv + * @param a_str_reply * @return */ -unsigned char* dap_server_db_hash_password(const char* a_password) -{ - static const unsigned char s_salt[]={ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; - static const size_t s_salt_size=sizeof (s_salt); - - unsigned char *md = DAP_NEW_Z_SIZE(unsigned char, DB_AUTH_HASH_LENGTH * 2); - - size_t a_password_length = strlen(a_password); - size_t l_str_length = a_password_length + s_salt_size; - unsigned char *l_str = DAP_NEW_Z_SIZE(unsigned char, l_str_length); - - memcpy(l_str, a_password, a_password_length); - memcpy(l_str + a_password_length, s_salt, s_salt_size); - SHA3_512(md, l_str, l_str_length); - SHA3_512(md + DB_AUTH_HASH_LENGTH, s_salt, s_salt_size); - - DAP_DELETE( l_str ); - return md; -} - -char* dap_server_db_hash_password_b64(const char* a_password) -{ - unsigned char* l_hash = dap_server_db_hash_password( a_password); - char * l_hash_str = DAP_NEW_Z_SIZE(char, 4 * DB_AUTH_HASH_LENGTH+1 ) ; - - if (!l_hash_str) { - DAP_DELETE( (char*)l_hash); - log_it(L_ERROR, "Can not memmory allocate"); - return NULL; - } - - dap_enc_base64_encode(l_hash, DB_AUTH_HASH_LENGTH * 2, l_hash_str,DAP_ENC_DATA_TYPE_B64_URLSAFE); - return l_hash_str; -} -/** - * @brief db_auth_login Authorization with user/password - * @param login ( login = email ) - * @param password Password - * @param domain - * @return codes: 1 = login ok, 2 = login not found in DataBase, - * 3 = incorrect password; 4 = subscribe client has been expiried - */ -int db_auth_login(const char* login, const char* password, - const char* domain, db_auth_info_t** ai) +int dap_chain_net_srv_vpn_cdb_auth_cli_cmd ( const char *a_user_str,int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply) { - *ai = NULL; - bson_t *doc; - - mongoc_collection_t *collection = mongoc_client_get_collection ( - mongo_client, s_db_name, "dap_users"); - - bson_t *query = bson_new(); - - if (strchr(login, '@')) - BSON_APPEND_UTF8 (query, "email", login); - else - BSON_APPEND_UTF8 (query, "login", login); - - mongoc_cursor_t *cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, - (const bson_t*)query, NULL, NULL); - - if ( mongoc_cursor_next (cursor, (const bson_t**)&doc) == false ) - { - mongoc_cursor_destroy (cursor); - bson_destroy (query); - mongoc_collection_destroy (collection); - log_it(L_WARNING, "%s not found in DataBase", login); - return 2; - } - - bson_iter_t iter; + 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; + 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); + + + 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,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 ); + } - unsigned const char* password_hash = dap_server_db_hash_password(password); - if (!password_hash) { - log_it(L_ERROR, "Can not memmory allocate"); - return 0; - } + 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 ); - unsigned char * password_hash_b64 = calloc(4 * DB_AUTH_HASH_LENGTH, sizeof(char)); + 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 (!password_hash_b64) { - free((char*)password_hash); - log_it(L_ERROR, "Can not memmory allocate"); - return 0; - } + 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 ); - dap_enc_base64_encode(password_hash, DB_AUTH_HASH_LENGTH * 2, password_hash_b64,DAP_ENC_DATA_TYPE_B64_URLSAFE); - - if (bson_iter_init (&iter, doc) && bson_iter_find (&iter, "expire_date")) { - if ( bson_iter_date_time(&iter) / 1000 < time(NULL) ) - { - log_it(L_WARNING, "Subscribe %s has been expiried", login); - return 4; + 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 - log_it(L_NOTICE, "Haven't found expire_date in collection"); - - if (bson_iter_init (&iter, doc) && bson_iter_find (&iter, "passwordHash")) { - if ( memcmp(password_hash_b64, bson_iter_value(&iter)->value.v_utf8.str, - DB_AUTH_HASH_LENGTH * 2) == 0 ) - { - { - bool b_error = false; - mongoc_collection_t *collection_dap_domain = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_domains"); - - bson_t *query = bson_new(); - - BSON_APPEND_UTF8 (query, "domain", domain); - mongoc_cursor_t *cursor_dap_domains = - mongoc_collection_find (collection_dap_domain, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - - bson_t *doc_dap_domain; - - if ( mongoc_cursor_next (cursor_dap_domains, (const bson_t**)&doc_dap_domain) == false ) - { - log_it(L_WARNING, "Login Error! " - "Domains not found in DataBase (collection dap_domains)"); - - b_error = true; + }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 } - mongoc_cursor_destroy (cursor_dap_domains); - bson_destroy (query); - if(doc_dap_domain) - bson_destroy (doc_dap_domain); - mongoc_collection_destroy (collection_dap_domain); - - //if(b_error) - // return 0; + 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 ); } - - log_it(L_INFO,"Login accepted"); - - *ai = DAP_NEW_Z(db_auth_info_t); - strncpy((*ai)->user,login,sizeof((*ai)->user)-1); - strncpy((*ai)->password,password,sizeof((*ai)->password)-1); - - if ( !bson_iter_init (&iter, doc) ) - log_it(L_ERROR,"Error iter init"); - - bson_oid_t oid; - - if ( bson_iter_find(&iter, "_id") ) - { - bson_oid_init_from_data(&oid, (const uint8_t*) &bson_iter_value(&iter)->value.v_oid.bytes); - bson_oid_to_string(&oid, (*ai)->id); + }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_password (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 { + l_ret = -9; + dap_string_append_printf(l_ret_str,"ERROR: Unknown error in password check for login '%s'\n", l_login_str ); } - else - log_it(L_ERROR,"Not find Id"); - - bson_iter_t sub_iter; - - if (bson_iter_init (&iter, doc) && - bson_iter_find_descendant (&iter, "profile.first_name", &sub_iter)) - strncpy((*ai)->first_name,bson_iter_value(&sub_iter)->value.v_utf8.str, - sizeof((*ai)->first_name)-1); - - if (bson_iter_init (&iter, doc) && - bson_iter_find_descendant (&iter, "profile.last_name", &sub_iter)) - strncpy((*ai)->last_name,bson_iter_value(&sub_iter)->value.v_utf8.str, - sizeof((*ai)->last_name)-1); - - if (bson_iter_init (&iter, doc) && - bson_iter_find_descendant (&iter, "profile.email", &sub_iter)) - strncpy((*ai)->email,bson_iter_value(&sub_iter)->value.v_utf8.str, - sizeof((*ai)->email)-1); - - for(int i=0; i < sizeof((*ai)->cookie); i++) - (*ai)->cookie[i] = 65 + rand() % 25; - - log_it(L_DEBUG,"Store cookie '%s' in the hash table",(*ai)->cookie); - s_save_cookie_inform_in_db(login, (*ai)); - pthread_mutex_lock(&s_mutex_on_auth_hash); - HASH_ADD_STR(s_auths,cookie,(*ai)); - pthread_mutex_unlock(&s_mutex_on_auth_hash); }else{ - log_it(L_WARNING, "Input password has hash %s but expected to have %s",password_hash_b64, bson_iter_value(&iter)->value.v_utf8.str ); + l_ret = -5; + dap_string_append_printf(l_ret_str,"ERROR: Need --login option\n" ); } - }else{ - log_it(L_WARNING, "No passwordHash in data"); - } + }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 ); + } - free(password_hash_b64); - free((char*)password_hash); - mongoc_cursor_destroy (cursor); - if(query) - bson_destroy (query); + 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 ); + } - if(doc) - bson_destroy (doc); - mongoc_collection_destroy (collection); + 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 ); + } - if( *ai == NULL ) - { - log_it (L_WARNING, "Incorrect password!"); - return 3; + 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; } - return 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; } -/** - * @brief db_auth_register Register new user in database - * @param user Login name - * @param password Password - * @param first_name First name - * @param last_name Last name - * @param email Email - * @details registerUser - * @return - */ -db_auth_info_t * db_auth_register(const char *user,const char *password, - const char *domain, const char * first_name, - const char* last_name, const char * email, - const char * device_type,const char *app_version, - const char *hostaddr, const char *sys_uuid ) -{ - mongoc_collection_t *collection_dap_domain = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_domains"); - - bson_t *query = bson_new(); - - BSON_APPEND_UTF8 (query, "domain", domain); - - mongoc_cursor_t *cursor_dap_domains = mongoc_collection_find - (collection_dap_domain, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - bson_t *doc_dap_domain; - - if ( mongoc_cursor_next (cursor_dap_domains, (const bson_t**)&doc_dap_domain) == false ) - { - log_it(L_WARNING, "Domain not found in DataBase (collection dap_domains) "); - return NULL; - } - - bson_iter_t iter; - bson_iter_init (&iter, doc_dap_domain); - if ( !bson_iter_find (&iter, "_id") ) - { - log_it(L_ERROR, "Where field _id in document?!"); - return NULL; - } - - mongoc_collection_t *collection = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_users"); - bson_error_t error; - - - - char * l_password_hash_b64 = dap_server_db_hash_password_b64(password); - - if (!l_password_hash_b64) { - log_it(L_ERROR, "Can not memmory allocate"); - return NULL; - } - - if (*l_password_hash_b64 == 0) { - log_it(L_ERROR, "Bad hash(based64) for user password"); - return NULL; - } - - bson_t *doc = BCON_NEW("login", user, - "passwordHash", l_password_hash_b64, - "domainId", BCON_OID((bson_oid_t*)bson_iter_value(&iter)->value.v_oid.bytes), - "email", email, - "profile", - "{", - "first_name", first_name, - "last_name", last_name, - "}", - "contacts" , "[","]"); - free(l_password_hash_b64); - - if (!mongoc_collection_insert (collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { - log_it (L_WARNING, "%s\n", error.message); - - bson_destroy(query); - mongoc_collection_destroy (collection_dap_domain); - bson_destroy(doc_dap_domain); - mongoc_cursor_destroy(cursor_dap_domains); - bson_destroy (doc); - mongoc_collection_destroy (collection); - mongoc_cleanup(); - return NULL; - } - else - { - db_auth_info_t * ai = DAP_NEW_Z(db_auth_info_t); - strncpy(ai->user,user,sizeof(ai->user)-1); - strncpy(ai->password,password,sizeof(ai->password)-1); - strncpy(ai->last_name,last_name,sizeof(ai->last_name)-1); - strncpy(ai->first_name,first_name,sizeof(ai->first_name)-1); - strncpy(ai->email,email,sizeof(ai->email)-1); - - for(int i=0;i<sizeof(ai->cookie);i++) - ai->cookie[i]=65+rand()%25; - - pthread_mutex_lock(&s_mutex_on_auth_hash); - HASH_ADD_STR(s_auths,cookie,ai); - pthread_mutex_unlock(&s_mutex_on_auth_hash); - - bson_destroy(query); - mongoc_collection_destroy (collection_dap_domain); - bson_destroy(doc_dap_domain); - mongoc_cursor_destroy(cursor_dap_domains); - bson_destroy (doc); - mongoc_collection_destroy (collection); - mongoc_cleanup(); - - return ai; - } - - return NULL; +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 db_auth_register_channel - * @param login - * @param password - * @details register channel - * @return + * @brief s_http_proc Process auth request + * @param sh HTTP simple client instance + * @param arg Return if ok */ -db_auth_info_t * db_auth_register_channel(const char* name_channel, const char* domain, - const char* password) -{ - mongoc_collection_t *collection_dap_domain = mongoc_client_get_collection - (mongo_client, s_db_name, "dap_domains"); - - bson_t *query = bson_new(); - - BSON_APPEND_UTF8 (query, "domain", domain); - - mongoc_cursor_t *cursor_dap_domains = - mongoc_collection_find (collection_dap_domain, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - - bson_t *doc_dap_domain; - - if ( mongoc_cursor_next (cursor_dap_domains, (const bson_t**)&doc_dap_domain) == false ) - { - log_it(L_WARNING, "Domain not found in DataBase (collection dap_domains) "); - return NULL; - } - - bson_iter_t iter; - bson_iter_init (&iter, doc_dap_domain); - if ( !bson_iter_find (&iter, "_id") ) - { - log_it(L_ERROR, "Where field _id in document?!"); - return NULL; - } - - mongoc_collection_t *collection = - mongoc_client_get_collection (mongo_client, s_db_name, "dap_channels"); - bson_error_t error; - - - char * l_password_hash_b64 = dap_server_db_hash_password_b64(password); - - bson_t *doc = BCON_NEW("name_channel", name_channel, - "passwordHash", l_password_hash_b64, - "domainId", BCON_OID((bson_oid_t*)bson_iter_value(&iter)->value.v_oid.bytes), - "subscribers", "[","]", - "last_id_message", BCON_INT32(0), - "messages","[","]"); - - DAP_DELETE( l_password_hash_b64 ); - if (!mongoc_collection_insert (collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { - log_it (L_ERROR, "%s\n", error.message); - bson_destroy(query); - bson_destroy(doc_dap_domain); - mongoc_cursor_destroy(cursor_dap_domains); - mongoc_collection_destroy(collection_dap_domain); - bson_destroy (doc); - mongoc_collection_destroy (collection); - mongoc_cleanup(); - return NULL; - } - - db_auth_info_t * ai = DAP_NEW_Z(db_auth_info_t); - strncpy(ai->user,name_channel,sizeof(ai->user)-1); - strncpy(ai->password,password,sizeof(ai->password)-1); - - for(size_t i=0;i<sizeof(ai->cookie);i++) - ai->cookie[i]=65+rand()%25; - - pthread_mutex_lock(&s_mutex_on_auth_hash); - HASH_ADD_STR(s_auths,cookie,ai); - pthread_mutex_unlock(&s_mutex_on_auth_hash); - - bson_destroy(query); - bson_destroy(doc_dap_domain); - mongoc_cursor_destroy(cursor_dap_domains); - mongoc_collection_destroy(collection_dap_domain); - bson_destroy (doc); - mongoc_collection_destroy (collection); - mongoc_cleanup(); - - return ai; -} - -bool exist_user_in_db(const char* user) +static void s_http_proc(dap_http_simple_t *a_http_simple, void * arg ) { - bool exist = true; - bson_t *doc = NULL; - - mongoc_collection_t *collection = mongoc_client_get_collection ( - mongo_client, s_db_name, "dap_users"); - - bson_t *query = bson_new(); - BSON_APPEND_UTF8 (query, "login", user); + 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(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 / "); - mongoc_cursor_t *cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, - (const bson_t*)query, NULL, NULL); + *return_code = Http_Status_BadRequest; + } - if ( mongoc_cursor_next (cursor, (const bson_t**)&doc) == false ) - { - exist = false; - log_it(L_WARNING, "Login not found in DataBase"); + 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"); } - - if(doc) - bson_destroy(doc); - - mongoc_cursor_destroy(cursor); - bson_destroy(query); - mongoc_collection_destroy(collection); - - return exist; } - - /** - * @brief db_auth_http_proc DB Auth http interface + * @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) */ -void db_auth_http_proc(enc_http_delegate_t *a_delegate, void * a_arg) +static void s_http_enc_proc(enc_http_delegate_t *a_delegate, void * a_arg) { http_status_code_t * return_code = (http_status_code_t*)a_arg; @@ -932,20 +425,14 @@ void db_auth_http_proc(enc_http_delegate_t *a_delegate, void * a_arg) return; }else{ if(strcmp(a_delegate->in_query,"logout")==0 ){ - db_auth_info_t * ai = s_info_by_cookie(a_delegate->cookie); - if(ai){ - log_it(L_DEBUG, "Cookie from %s user accepted, 0x%032llX session",ai->user,ai->id); - pthread_mutex_lock(&s_mutex_on_auth_hash); - HASH_DEL(s_auths,ai); - pthread_mutex_unlock(&s_mutex_on_auth_hash); - free(ai); + 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" ); *return_code = Http_Status_OK; }else{ - log_it(L_NOTICE,"Logout action: session 0x%032llX is already logouted (by timeout?)",ai->id); + 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" @@ -954,152 +441,169 @@ void db_auth_http_proc(enc_http_delegate_t *a_delegate, void * a_arg) } }else if(strcmp(a_delegate->in_query,"login")==0 ){ - char l_user[256]={0}; - char l_password[1024]={0}; - char l_domain[64]={0}; + char l_login[128]={0}; + char l_password[256]={0}; char l_pkey[4096]={0}; - char l_something[64] = {0}; - if(sscanf(a_delegate->request_str,"%255s %1023s %63s %4095s %64s",l_user,l_password,l_domain,l_pkey,l_something)>=3){ - log_it(L_INFO, "Trying to login with username '%s'",l_user); + char l_domain[64], l_domain2[64]; - if(!check_user_data_for_space(strlen(a_delegate->request_str), strlen(l_user) + strlen(l_password) + strlen(l_domain) + strlen(l_pkey) + strlen(l_something))){ - log_it(L_WARNING,"Wrong symbols in username or password or domain, misfit is %d", strlen(a_delegate->request_str) - strlen(l_user) - strlen(l_password) - strlen(l_domain) - strlen(l_pkey) - strlen(l_something)); - //log_it(L_WARNING, "l_user size: %d", strlen(l_user)); - //log_it(L_WARNING, "l_pass size: %d", strlen(l_password)); - //log_it(L_WARNING, "l_pkey size: %d", strlen(l_pkey)); - log_it(L_DEBUG,"%s@%s", l_user, l_password); + if( sscanf(a_delegate->request_str,"%127s %255s %4095s ",l_login,l_password,l_pkey) >=3 || + sscanf(a_delegate->request_str,"%127s %255s %63s %4095s %63s",l_login,l_password,l_domain, l_pkey, l_domain2) >=4 ){ + 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); *return_code = Http_Status_BadRequest; return; } -// if(db_input_validation(user)==0){ -// log_it(L_WARNING,"Wrong symbols in username '%s'",user); -// enc_http_reply_f(dg, OP_CODE_INCORRECT_SYMOLS); -// *return_code = Http_Status_BadRequest; -// return; -// } -// if(db_input_validation(password)==0){ -// log_it(L_WARNING,"Wrong symbols in password"); -// enc_http_reply_f(dg, OP_CODE_INCORRECT_SYMOLS); -// *return_code = Http_Status_BadRequest; -// return; -// } -// if(db_input_validation(domain)==0){ -// log_it(L_WARNING,"Wrong symbols in domain"); -// enc_http_reply_f(dg, OP_CODE_INCORRECT_SYMOLS); -// *return_code = Http_Status_BadRequest; -// return; -// } - - db_auth_info_t * l_auth_info = NULL; - short login_result = db_auth_login(l_user, l_password, l_domain, &l_auth_info); - switch (login_result) { - case 1: - l_auth_info->dap_http_client = a_delegate->http; - l_auth_info->auth_date = time(NULL); - if (l_pkey[0] ) - strncpy(l_auth_info->pkey,l_pkey, sizeof (l_auth_info->pkey)-1); - 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<first_name>%s</first_name>\n",l_auth_info->first_name); - enc_http_reply_f(a_delegate,"\t<last_name>%s</last_name>\n",l_auth_info->last_name); - enc_http_reply_f(a_delegate,"\t<cookie>%s</cookie>\n",l_auth_info->cookie); - if (s_callback_success) - s_callback_success (a_delegate, l_auth_info); // 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_user); - *return_code = Http_Status_OK; - break; - case 2: - enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB); - *return_code = Http_Status_OK; - break; - case 3: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_PSWD); - *return_code = Http_Status_OK; - break; - case 4: - enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED); - *return_code = Http_Status_PaymentRequired; - break; - default: - log_it(L_DEBUG, "Login: wrong password for user %s",l_user); + 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); + *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); *return_code = Http_Status_BadRequest; - break; + return; + } + + int l_login_result = dap_chain_net_srv_vpn_cdb_auth_check_password( 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); + time_t * l_ts_last_logined= (time_t*) dap_chain_global_db_gr_get( l_login , &l_tmp_size,s_group_ts_last_login); + + 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 ( 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); + *return_code = Http_Status_OK; + + DAP_DELETE(l_first_name); + DAP_DELETE(l_last_name); + DAP_DELETE(l_email); + DAP_DELETE(l_ts_last_logined); + + // Update last logined + l_ts_last_logined = DAP_NEW_Z(time_t); + *l_ts_last_logined = time(NULL); + + dap_chain_global_db_gr_set( dap_strdup( l_login), l_ts_last_logined, sizeof (time_t), s_group_ts_last_login ); + }break; + case -1: + enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB); + *return_code = Http_Status_OK; + break; + case -2: + enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_PSWD); + *return_code = Http_Status_OK; + break; + case 4: + enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED); + *return_code = Http_Status_PaymentRequired; + break; + default: + log_it(L_WARNING, "Login: Unknown authorize error for login '%s'",l_login); + *return_code = Http_Status_BadRequest; + break; } }else{ log_it(L_DEBUG, "Login: wrong auth's request body "); *return_code = Http_Status_BadRequest; } - }else if (strcmp(a_delegate->in_query,"register")==0){ - char user[256]; - char password[1024]; - char domain[64]; - char first_name[1024]; - char last_name[1024]; - // char phone_number[1024]; - - char email[1024]; - char device_type[32]; - char app_version[32]; - char sys_uuid[128]; + }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,"%255s %63s %1023s %1023s %1023s %1023s %32s %128s" - ,user,password,domain,first_name,last_name,email,device_type,app_version)>=7){ - if(db_input_validation(user)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the username '%s'",user); - *return_code = Http_Status_BadRequest; - return; - } - if(db_input_validation(password)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the password"); + 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); *return_code = Http_Status_BadRequest; return; } - if(db_input_validation(domain)==0){ + if(s_input_validation(l_password)==0){ log_it(L_WARNING,"Registration: Wrong symbols in the password"); *return_code = Http_Status_BadRequest; return; } - if(db_input_validation(first_name)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the first name '%s'",first_name); + if(s_input_validation(l_first_name)==0){ + log_it(L_WARNING,"Registration: Wrong symbols in the first name '%s'",l_first_name); *return_code = Http_Status_BadRequest; return; } - if(db_input_validation(last_name)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the last name '%s'",last_name); + if(s_input_validation(l_last_name)==0){ + log_it(L_WARNING,"Registration: Wrong symbols in the last name '%s'",l_last_name); *return_code = Http_Status_BadRequest; return; } - if(db_input_validation(email)==0){ - log_it(L_WARNING,"Registration: Wrong symbols in the email '%s'",email); + if(s_input_validation(l_email)==0){ + log_it(L_WARNING,"Registration: Wrong symbols in the email '%s'",l_email); *return_code = Http_Status_BadRequest; return; } + if ( l_login[0] && l_password[0] && l_email[0] ){ - db_auth_info_t * ai = db_auth_register(user,password,domain,first_name,last_name,email, - device_type,app_version,a_delegate->http->client->hostaddr,sys_uuid); + // 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,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 ); - if(ai != NULL) - { 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<first_name>%s</first_name>\n",ai->first_name); - enc_http_reply_f(a_delegate,"\t<last_name>%s</last_name>\n",ai->last_name); - enc_http_reply_f(a_delegate,"\t<cookie>%s</cookie>\n",ai->cookie); + + 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",user,first_name,last_name,email); - } - else { - log_it(L_WARNING, "User not registered. Maybe login already exists"); + 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 "); @@ -1116,68 +620,8 @@ void db_auth_http_proc(enc_http_delegate_t *a_delegate, void * a_arg) } } -static bool mongod_is_running() -{ - int pfd[2]; - pipe(pfd); - - pid_t childpid; - - if((childpid = fork()) == -1) - { - log_it(L_ERROR,"Error fork()"); - return false; - } - - if(childpid == 0) - { - close(STDOUT_FILENO); - dup2(pfd[1], STDOUT_FILENO); - close(pfd[0]); - close(pfd[1]); - execlp("pgrep", "pgrep","mongod", NULL); - exit(0); - } - waitpid(childpid, 0, 0); - char readbuffer[10] = {'\0'}; - - int flags = fcntl(pfd[0], F_GETFL, 0); - fcntl(pfd[0], F_SETFL, flags | O_NONBLOCK); - read(pfd[0], readbuffer, sizeof(readbuffer)); - - if(readbuffer[0] == '\0') - { - log_it(L_ERROR,"MongoDB service not running. For start use: \"mongod\" in terminal"); - return false; - } - - close(pfd[0]); - close(pfd[1]); - - return true; -} - - - -/// Check user data for correct input. -/// @param before_parsing Line size before parsing. -/// @param after_parsing Line size after parsing. -/// @return Returns true if user data is entered correctly -/// (there are 2 separator spaces), otherwise false. -bool check_user_data_for_space(size_t before_parsing, size_t after_parsing) -{ - return (before_parsing - after_parsing) == 3; -} - - - - -int dap_chain_net_srv_vpn_cdb_auth_add_proc(dap_http_t * a_http, const char * a_url) -{ - -} diff --git a/dap_chain_net_srv_vpn_cdb_auth.h b/dap_chain_net_srv_vpn_cdb_auth.h index 4d979baa9665d8467305b512db170a0e933cc2ce..a8ad01d28010eee3f0ce25cdfbe5cf926eca522a 100644 --- a/dap_chain_net_srv_vpn_cdb_auth.h +++ b/dap_chain_net_srv_vpn_cdb_auth.h @@ -27,5 +27,11 @@ #include "dap_http.h" #include "dap_enc_http.h" -int dap_chain_net_srv_vpn_cdb_auth_add_proc(dap_http_t * a_http, const char * a_url); +int dap_chain_net_srv_vpn_cdb_auth_init (const char * a_domain, bool a_is_registration_open); +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 ( 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_password(const char * a_login, const char * a_password);