Skip to content

Commit

Permalink
Merge pull request #1402 from atsign-foundation/c-sshnpd-permit-open
Browse files Browse the repository at this point in the history
feat: permit-open
  • Loading branch information
gkc authored Oct 1, 2024
2 parents b9982df + ebb1072 commit 0379157
Show file tree
Hide file tree
Showing 14 changed files with 748 additions and 140 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/c_unit_tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: C Unit Tests

on:
workflow_dispatch:
push:
branches: [trunk]
pull_request:
branches: [trunk]

permissions: # added using https://github.com/step-security/secure-repo
contents: read

jobs:
unit-tests:
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

- name: sshnpd Unit CTest
working-directory: packages/c
run: |
cmake -S . -B build -DSSHNPD_BUILD_TESTS=ON
cmake --build build
ctest --test-dir build/sshnpd/tests --output-on-failure --timeout 2
1 change: 1 addition & 0 deletions packages/c/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ compile_commands.json

core
valgrind-out.txt*
Testing/
1 change: 1 addition & 0 deletions packages/c/sshnpd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ set(
${CMAKE_CURRENT_LIST_DIR}/src/handler_commons.c
${CMAKE_CURRENT_LIST_DIR}/src/main.c
${CMAKE_CURRENT_LIST_DIR}/src/params.c
${CMAKE_CURRENT_LIST_DIR}/src/permitopen.c
${CMAKE_CURRENT_LIST_DIR}/src/run_srv_process.c
)

Expand Down
5 changes: 4 additions & 1 deletion packages/c/sshnpd/include/sshnpd/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ struct _sshnpd_params {
size_t manager_list_len;
char **manager_list;

char *policy;

size_t permitopen_len;
char **permitopen;
char **permitopen_hosts;
uint16_t *permitopen_ports; // 0 = '*'
char *permitopen_str;
bool should_free_permitopen_str;

Expand Down
25 changes: 25 additions & 0 deletions packages/c/sshnpd/include/sshnpd/permitopen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef SSHNPD_PERMITOPEN_H
#define SSHNPD_PERMITOPEN_H
#include <atlogger/atlogger.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

// atlogger won't be available during the initial parsing of the parameters
// (since we are waiting for the verbose flag to be set)
int parse_permitopen(char *input, char ***permitopen_hosts, uint16_t **permitopen_ports, size_t *permitopen_len,
bool is_logger_available);

struct _permitopen_params {
char *requested_host;
uint16_t requested_port;

char **permitopen_hosts;
uint16_t *permitopen_ports;
size_t permitopen_len;
};

typedef struct _permitopen_params permitopen_params;

bool should_permitopen(struct _permitopen_params *params);
#endif
1 change: 1 addition & 0 deletions packages/c/sshnpd/src/background_jobs.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ void *refresh_device_entry(void *void_refresh_device_entry_params) {
}

// Build each atkey
// TODO: @xavierchanth - review this implementation
int interval_seconds = 60 * 60; // once an hour
int counter = 0;
while (*params->should_run) {
Expand Down
65 changes: 39 additions & 26 deletions packages/c/sshnpd/src/handle_npt_request.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "atclient/request_options.h"
#include "sshnpd/params.h"
#include "sshnpd/permitopen.h"
#include "sshnpd/sshnpd.h"
#include <atchops/aes.h>
#include <atchops/base64.h>
Expand Down Expand Up @@ -106,6 +106,24 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
return;
}

// NPT ONLY
// Don't try optimizing this to reuse the permitopen struct from main.c.
// none of the memory duplication here is expensive, and it's a surface for bugs
permitopen_params permitopen;
permitopen.permitopen_len = params->permitopen_len;
permitopen.permitopen_hosts = params->permitopen_hosts;
permitopen.permitopen_ports = params->permitopen_ports;
permitopen.requested_host = cJSON_GetStringValue(requested_host);
permitopen.requested_port = cJSON_GetNumberValue(requested_port);

if (!should_permitopen(&permitopen)) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "Ignoring request to localhost:%d\n",
permitopen.requested_port);
cJSON_Delete(envelope);
return;
}
// END NPT ONLY

// These values do not need to be asserted for v4 compatibility, only for v5

cJSON *auth_to_rvd = cJSON_GetObjectItem(payload, "authenticateToRvd");
Expand Down Expand Up @@ -138,15 +156,13 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
char *buffer = NULL;

res = atclient_get_public_key(atclient, &atkey, &buffer, NULL);
atclient_atkey_free(&atkey);
if (res != 0) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to get public key\n");
atclient_atkey_free(&atkey);
cJSON_Delete(envelope);
return;
}

atclient_atkey_free(&atkey);

atchops_rsa_key_public_key requesting_atsign_publickey;
atchops_rsa_key_public_key_init(&requesting_atsign_publickey);

Expand Down Expand Up @@ -272,7 +288,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
if (!encrypt_rvd_traffic) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "encryptRvdTraffic=false is not supported by this daemon\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -284,7 +300,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
"encryptRvdTraffic was requested, but no client ephemeral public key / key type was provided\n");

if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -294,7 +310,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
if ((res = atchops_aes_generate_key(key, ATCHOPS_AES_256)) != 0) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to generate session aes key\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -305,7 +321,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
if (res != 0) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to generate session aes key\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -315,7 +331,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
if ((res = atchops_iv_generate(iv)) != 0) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to generate session iv\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -326,7 +342,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
if (res != 0) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to generate session iv\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -348,7 +364,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to populate client ephemeral pk\n");
atchops_rsa_key_public_key_free(&ac);
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -360,7 +376,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
"Failed to allocate memory to encrypt the session aes key\n");
atchops_rsa_key_public_key_free(&ac);
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand All @@ -371,7 +387,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to encrypt the session aes key\n");
atchops_rsa_key_public_key_free(&ac);
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
free(session_aes_key_encrypted);
cJSON_Delete(envelope);
Expand All @@ -387,7 +403,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
"Failed to allocate memory to base64 encode the session aes key\n");
atchops_rsa_key_public_key_free(&ac);
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
free(session_aes_key_encrypted);
cJSON_Delete(envelope);
Expand All @@ -402,7 +418,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to base64 encode the session aes key\n");
atchops_rsa_key_public_key_free(&ac);
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
free(session_aes_key_base64);
free(session_aes_key_encrypted);
Expand All @@ -418,7 +434,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to allocate memory to encrypt the session iv\n");
atchops_rsa_key_public_key_free(&ac);
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
free(session_aes_key_base64);
cJSON_Delete(envelope);
Expand All @@ -431,7 +447,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
if (res != 0) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to encrypt the session iv\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
free(session_iv_encrypted);
free(session_aes_key_base64);
Expand All @@ -446,7 +462,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR,
"Failed to allocate memory to base64 encode the session iv\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
free(session_iv_encrypted);
free(session_aes_key_base64);
Expand All @@ -461,7 +477,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
if (res != 0) {
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to base64 encode the session iv\n");
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
free(session_iv_base64);
free(session_iv_encrypted);
Expand All @@ -480,7 +496,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
atlogger_log(LOGGER_TAG, ATLOGGER_LOGGING_LEVEL_ERROR,
"%s is not an accepted key type for encrypting the aes key\n", pk_type);
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
return;
Expand Down Expand Up @@ -517,13 +533,10 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn

int res = run_srv_process(rvd_host_str, rvd_port_int, requested_host_str, requested_port_int, authenticate_to_rvd,
rvd_auth_string, encrypt_rvd_traffic, multi, session_aes_key, session_iv);
free(rvd_host_str);
free(requested_host_str);

*is_child_process = true;

if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
cJSON_Delete(envelope);
exit(res);
Expand Down Expand Up @@ -652,7 +665,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
clean_res: { free(keyname); }
clean_final_res_value: {
atclient_atkey_free(&final_res_atkey);
free(final_res_value);
cJSON_free(final_res_value);
}
clean_json: {
cJSON_Delete(final_res_envelope);
Expand All @@ -665,7 +678,7 @@ void handle_npt_request(atclient *atclient, pthread_mutex_t *atclient_lock, sshn
}
cancel:
if (authenticate_to_rvd) {
free(rvd_auth_string);
cJSON_free(rvd_auth_string);
}
if (free_session_base64) {
free(session_iv_base64);
Expand Down
Loading

0 comments on commit 0379157

Please sign in to comment.