aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt4
-rw-r--r--bastion/CMakeLists.txt4
-rw-r--r--bastion/main.c116
-rw-r--r--common/config.c4
-rw-r--r--common/config.h.in4
-rw-r--r--external/CMakeLists.txt3
m---------external/parg0
8 files changed, 112 insertions, 26 deletions
diff --git a/.gitmodules b/.gitmodules
index 21d232a..3d4e4bd 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "external/uthash"]
path = external/uthash
url = https://github.com/troydhanson/uthash
+[submodule "external/parg"]
+ path = external/parg
+ url = https://github.com/jibsen/parg
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0432691..29e1aa6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.0)
-project(bastion LANGUAGES C VERSION 0.1.2)
+project(bastion LANGUAGES C VERSION 0.1.3)
set(CMAKE_VERBOSE_MAKEFILE FALSE)
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
@@ -26,6 +26,8 @@ if(SESSION_RECORDING)
add_definitions(-DSESSION_RECORDING)
endif()
+execute_process(COMMAND git rev-parse HEAD RESULT_VARIABLE GIT_HASH_RESULT OUTPUT_VARIABLE GIT_HASH_FULL)
+string(STRIP ${GIT_HASH_FULL} GIT_HASH)
configure_file("common/config.h.in" "common/config.h")
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/bastion/CMakeLists.txt b/bastion/CMakeLists.txt
index 4f622e0..89d31c5 100644
--- a/bastion/CMakeLists.txt
+++ b/bastion/CMakeLists.txt
@@ -1,3 +1,4 @@
+include_directories("${PROJECT_SOURCE_DIR}/external/parg/")
include_directories("${PROJECT_SOURCE_DIR}/external/termrec/libtty")
file(GLOB_RECURSE SOURCES *.c)
@@ -7,7 +8,8 @@ target_link_libraries(bastion common)
if (SESSION_RECORDING)
target_link_libraries(bastion libtty)
endif()
-target_link_libraries(bastion bz2 config curl lzma ssh z)
+target_link_libraries(bastion libparg)
+target_link_libraries(bastion bz2 config curl lzma pthread ssh z)
install(TARGETS bastion DESTINATION bin)
diff --git a/bastion/main.c b/bastion/main.c
index d4fb321..9f834b0 100644
--- a/bastion/main.c
+++ b/bastion/main.c
@@ -1,5 +1,6 @@
#include <libssh/callbacks.h>
#include <libssh/server.h>
+#include <parg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
@@ -8,6 +9,16 @@
#include "session.h"
#include "state.h"
+static void usage(char **argv)
+{
+ printf("Usage: %s [-h] [-v] [-t] [-f] [-c STRING]\n", argv[0]);
+ printf(" -h : show this help message and exit\n");
+ printf(" -v : show version and exit\n");
+ printf(" -t : test configuration file and exit\n");
+ printf(" -f : stay in foreground (don't fork)\n");
+ printf(" -c : specify a path to a configuration file to use instead of the default %s\n", CONFIG_PATH);
+}
+
/* SIGCHLD handler for cleaning up dead children. */
static void sigchld_handler(int signo) {
(void) signo;
@@ -30,17 +41,8 @@ __attribute__((noreturn)) static void sigint_handler(int signo)
exit(0);
}
-int main()
+int main(int argc, char **argv)
{
- // Set up SIGCHLD handler
- struct sigaction sa;
- sa.sa_handler = sigchld_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
- if (sigaction(SIGCHLD, &sa, NULL) != 0) {
- fprintf(stderr, "Failed to register SIGCHLD handler\n");
- return 1;
- }
// Set up SIGINT handler
struct sigaction sa2;
sa2.sa_handler = sigint_handler;
@@ -48,21 +50,86 @@ int main()
sa2.sa_flags = 0;
if (sigaction(SIGINT, &sa2, NULL) != 0) {
fprintf(stderr, "Failed to register SIGINT handler\n");
- return 2;
+ return 1;
+ }
+
+ // Argument parsing
+ struct parg_state ps;
+ int c;
+ char test_only = 0, dont_fork = 0;
+ const char *config_file = CONFIG_PATH;
+ parg_init(&ps);
+ //while ((int c = parg_getopt(&ps, argc, argv, "hs:v")) != -1) {
+ while ((c = parg_getopt(&ps, argc, argv, "hvtfc:")) != -1) {
+ switch (c) {
+ case 1:
+ printf("invalid non option '%s'\n", ps.optarg);
+ return 2;
+ case 'h':
+ usage(argv);
+ return 0;
+ case 'v':
+ printf("%s %s - %s\n", argv[0], VERSION, GIT_HASH);
+ return 0;
+ case 't':
+ test_only = 1;
+ break;
+ case 'f':
+ dont_fork = 1;
+ break;
+ case 'c':
+ config_file = ps.optarg;
+ break;
+ case '?':
+ if (ps.optopt == 'c') {
+ printf("option -c requires the path to a configuration in argument.\n");
+ }
+ else {
+ printf("unknown option -%c\n", ps.optopt);
+ }
+ usage(argv);
+ return 3;
+ default:
+ printf("error: unhandled option -%c\n", c);
+ return 4;
+ break;
+ }
+ }
+
+ if (test_only) {
+ if (config_load(config_file) != 0) {
+ fprintf(stderr, "Failed to load configuration file %s.\n", CONFIG_PATH);
+ config_clean();
+ return 5;
+ }
+ config_clean();
+ return 0;
+ }
+
+ struct sigaction sa;
+ if (!dont_fork) {
+ // Set up SIGCHLD handler
+ sa.sa_handler = sigchld_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+ if (sigaction(SIGCHLD, &sa, NULL) != 0) {
+ fprintf(stderr, "Failed to register SIGCHLD handler\n");
+ return 6;
+ }
}
// Initializing ssh context
if (ssh_init() != 0) {
fprintf(stderr, "Failed to initialize libssh global cryptographic data structures.\n");
- return 3;
+ return 7;
};
// Initializing configuration context
- if (config_load() != 0) {
+ if (config_load(config_file) != 0) {
fprintf(stderr, "Failed to load configuration file %s.\n", CONFIG_PATH);
config_clean();
ssh_finalize();
- return 4;
+ return 8;
}
// Initializing ssh_bind
@@ -71,7 +138,7 @@ int main()
fprintf(stderr, "Error initializing ssh_bind\n");
config_clean();
ssh_finalize();
- return 5;
+ return 9;
}
int listen_port = config_get_port();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &listen_port);
@@ -84,7 +151,7 @@ int main()
ssh_bind_free(sshbind);
config_clean();
ssh_finalize();
- return 6;
+ return 10;
}
while (1) {
@@ -100,11 +167,18 @@ int main()
// Blocks until there is a new incoming connection
if (ssh_bind_accept(sshbind,session) == SSH_OK){
- switch(fork()) {
+ int res = 0;
+ if (!dont_fork) {
+ res = fork();
+ }
+
+ switch(res) {
case 0:
- /* Remove the SIGCHLD handler inherited from parent. */
- sa.sa_handler = SIG_DFL;
- sigaction(SIGCHLD, &sa, NULL);
+ if (!dont_fork) {
+ /* Remove the SIGCHLD handler inherited from parent. */
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &sa, NULL);
+ }
/* Remove socket binding, which allows us to restart the parent process, without terminating existing sessions. */
ssh_bind_free(sshbind);
sshbind = NULL;
@@ -134,7 +208,7 @@ int main()
ssh_bind_free(sshbind);
config_clean();
ssh_finalize();
- return 7;
+ return 10;
}
/* Since the session has been passed to a child fork, do some cleaning up at the parent process. */
ssh_disconnect(session);
diff --git a/common/config.c b/common/config.c
index 1c45e7e..11a06d7 100644
--- a/common/config.c
+++ b/common/config.c
@@ -7,12 +7,12 @@
config_t * config = NULL;
char // returns 0 if ok, greater than 0 otherwise
-config_load(void)
+config_load(const char *config_file)
{
config = malloc(sizeof(config_t));
config_init(config);
config_set_tab_width(config, 4);
- if (config_read_file(config, CONFIG_PATH) != CONFIG_TRUE) {
+ if (config_read_file(config, config_file) != CONFIG_TRUE) {
switch(config_error_type(config)) {
case CONFIG_ERR_NONE:
fprintf(stderr, "Configuration read error with none type reported... This shouldn't happen!\n");
diff --git a/common/config.h.in b/common/config.h.in
index 95d43c9..a671414 100644
--- a/common/config.h.in
+++ b/common/config.h.in
@@ -3,6 +3,8 @@
#define CONFIG_DIR "@CMAKE_INSTALL_PREFIX@/etc/bastion/"
#define CONFIG_PATH CONFIG_DIR "bastion.conf"
+#define VERSION "@PROJECT_VERSION@"
+#define GIT_HASH "@GIT_HASH@"
#define MAX_HOSTNAME_LENGTH 64
@@ -17,7 +19,7 @@
#define SESSION_RECORDING_DIRECTORY_MODE S_IRUSR | S_IWUSR | S_IXUSR
#endif
-char config_load(void);
+char config_load(const char *config_file);
int config_get_port(void);
const char * config_get_key_dsa(void);
const char * config_get_key_rsa(void);
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index 9aa3ee0..34f3cd4 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -34,3 +34,6 @@ if (SESSION_RECORDING)
target_link_libraries(termplay bz2 curl lzma pthread z)
install(TARGETS termplay DESTINATION bin)
endif()
+
+# Build parg library for argument parsing
+add_library(libparg parg/parg.c parg/parg.h)
diff --git a/external/parg b/external/parg
new file mode 160000
+Subproject 97f3a075109ebace4f660fb341c6b99b2a4b092