diff --git a/dap-sdk/core/src/dap_fnmatch.c b/dap-sdk/core/src/dap_fnmatch.c index 21096cf46828208d76ad0e0e54158b6f36eabf37..f89fa536eff2959625980c269d6dd60e5f42d784 100644 --- a/dap-sdk/core/src/dap_fnmatch.c +++ b/dap-sdk/core/src/dap_fnmatch.c @@ -179,7 +179,7 @@ __wcschrnul (const wchar_t *s, wint_t c) # endif # define STRLEN(S) strlen(S) # define STRCAT(D, S) strcat (D, S) -# define MEMPCPY(D, S, N) __mempcpy (D, S, N) +# 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 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/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 ed75611c32415c6ae8195bb6ef06a52cfc00d79e..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: { 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/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/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/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 6db28cf82c6a3d5cae62933b56dd47fac8517a9d..7d18a4d996e72920f61074bcba5f4eb585816ffb 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"); diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 7243d534264a8cf343ede61b62874a71ca124758..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 @@ -1014,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); @@ -1029,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; } @@ -1038,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; @@ -1060,7 +1089,7 @@ 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); } @@ -1106,6 +1135,7 @@ void s_set_reply_text_node_status(char **a_str_reply, dap_chain_net_t * a_net){ */ 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; @@ -1141,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 ) { @@ -1278,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; @@ -1309,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/"); @@ -1331,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" ) ) ); @@ -1850,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 @@ -2408,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_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/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index edcbffcbf3927be70cf4f4525f911a1659804566..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);