Archived
1
0
Fork 0

Added argument parsing with libparg, along with usefull running modes

This commit is contained in:
Julien Dessaux 2019-04-01 14:19:42 +02:00
parent a6f8d1da2a
commit b372795ac7
8 changed files with 113 additions and 26 deletions

3
.gitmodules vendored
View file

@ -4,3 +4,6 @@
[submodule "external/uthash"] [submodule "external/uthash"]
path = external/uthash path = external/uthash
url = https://github.com/troydhanson/uthash url = https://github.com/troydhanson/uthash
[submodule "external/parg"]
path = external/parg
url = https://github.com/jibsen/parg

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.0) 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) set(CMAKE_VERBOSE_MAKEFILE FALSE)
if(EXISTS "${CMAKE_SOURCE_DIR}/.git") if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
@ -26,6 +26,8 @@ if(SESSION_RECORDING)
add_definitions(-DSESSION_RECORDING) add_definitions(-DSESSION_RECORDING)
endif() 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") configure_file("common/config.h.in" "common/config.h")
include_directories("${CMAKE_CURRENT_BINARY_DIR}") include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}")

View file

@ -1,3 +1,4 @@
include_directories("${PROJECT_SOURCE_DIR}/external/parg/")
include_directories("${PROJECT_SOURCE_DIR}/external/termrec/libtty") include_directories("${PROJECT_SOURCE_DIR}/external/termrec/libtty")
file(GLOB_RECURSE SOURCES *.c) file(GLOB_RECURSE SOURCES *.c)
@ -7,7 +8,8 @@ target_link_libraries(bastion common)
if (SESSION_RECORDING) if (SESSION_RECORDING)
target_link_libraries(bastion libtty) target_link_libraries(bastion libtty)
endif() 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) install(TARGETS bastion DESTINATION bin)

View file

@ -1,5 +1,6 @@
#include <libssh/callbacks.h> #include <libssh/callbacks.h>
#include <libssh/server.h> #include <libssh/server.h>
#include <parg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -8,6 +9,16 @@
#include "session.h" #include "session.h"
#include "state.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. */ /* SIGCHLD handler for cleaning up dead children. */
static void sigchld_handler(int signo) { static void sigchld_handler(int signo) {
(void) signo; (void) signo;
@ -30,17 +41,8 @@ __attribute__((noreturn)) static void sigint_handler(int signo)
exit(0); 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 // Set up SIGINT handler
struct sigaction sa2; struct sigaction sa2;
sa2.sa_handler = sigint_handler; sa2.sa_handler = sigint_handler;
@ -48,21 +50,86 @@ int main()
sa2.sa_flags = 0; sa2.sa_flags = 0;
if (sigaction(SIGINT, &sa2, NULL) != 0) { if (sigaction(SIGINT, &sa2, NULL) != 0) {
fprintf(stderr, "Failed to register SIGINT handler\n"); fprintf(stderr, "Failed to register SIGINT handler\n");
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; 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 // Initializing ssh context
if (ssh_init() != 0) { if (ssh_init() != 0) {
fprintf(stderr, "Failed to initialize libssh global cryptographic data structures.\n"); fprintf(stderr, "Failed to initialize libssh global cryptographic data structures.\n");
return 3; return 7;
}; };
// Initializing configuration context // Initializing configuration context
if (config_load() != 0) { if (config_load(config_file) != 0) {
fprintf(stderr, "Failed to load configuration file %s.\n", CONFIG_PATH); fprintf(stderr, "Failed to load configuration file %s.\n", CONFIG_PATH);
config_clean(); config_clean();
ssh_finalize(); ssh_finalize();
return 4; return 8;
} }
// Initializing ssh_bind // Initializing ssh_bind
@ -71,7 +138,7 @@ int main()
fprintf(stderr, "Error initializing ssh_bind\n"); fprintf(stderr, "Error initializing ssh_bind\n");
config_clean(); config_clean();
ssh_finalize(); ssh_finalize();
return 5; return 9;
} }
int listen_port = config_get_port(); int listen_port = config_get_port();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &listen_port); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &listen_port);
@ -84,7 +151,7 @@ int main()
ssh_bind_free(sshbind); ssh_bind_free(sshbind);
config_clean(); config_clean();
ssh_finalize(); ssh_finalize();
return 6; return 10;
} }
while (1) { while (1) {
@ -100,11 +167,18 @@ int main()
// Blocks until there is a new incoming connection // Blocks until there is a new incoming connection
if (ssh_bind_accept(sshbind,session) == SSH_OK){ if (ssh_bind_accept(sshbind,session) == SSH_OK){
switch(fork()) { int res = 0;
if (!dont_fork) {
res = fork();
}
switch(res) {
case 0: case 0:
if (!dont_fork) {
/* Remove the SIGCHLD handler inherited from parent. */ /* Remove the SIGCHLD handler inherited from parent. */
sa.sa_handler = SIG_DFL; sa.sa_handler = SIG_DFL;
sigaction(SIGCHLD, &sa, NULL); sigaction(SIGCHLD, &sa, NULL);
}
/* Remove socket binding, which allows us to restart the parent process, without terminating existing sessions. */ /* Remove socket binding, which allows us to restart the parent process, without terminating existing sessions. */
ssh_bind_free(sshbind); ssh_bind_free(sshbind);
sshbind = NULL; sshbind = NULL;
@ -134,7 +208,7 @@ int main()
ssh_bind_free(sshbind); ssh_bind_free(sshbind);
config_clean(); config_clean();
ssh_finalize(); ssh_finalize();
return 7; return 10;
} }
/* Since the session has been passed to a child fork, do some cleaning up at the parent process. */ /* Since the session has been passed to a child fork, do some cleaning up at the parent process. */
ssh_disconnect(session); ssh_disconnect(session);

View file

@ -7,12 +7,12 @@
config_t * config = NULL; config_t * config = NULL;
char // returns 0 if ok, greater than 0 otherwise char // returns 0 if ok, greater than 0 otherwise
config_load(void) config_load(const char *config_file)
{ {
config = malloc(sizeof(config_t)); config = malloc(sizeof(config_t));
config_init(config); config_init(config);
config_set_tab_width(config, 4); 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)) { switch(config_error_type(config)) {
case CONFIG_ERR_NONE: case CONFIG_ERR_NONE:
fprintf(stderr, "Configuration read error with none type reported... This shouldn't happen!\n"); fprintf(stderr, "Configuration read error with none type reported... This shouldn't happen!\n");

View file

@ -3,6 +3,8 @@
#define CONFIG_DIR "@CMAKE_INSTALL_PREFIX@/etc/bastion/" #define CONFIG_DIR "@CMAKE_INSTALL_PREFIX@/etc/bastion/"
#define CONFIG_PATH CONFIG_DIR "bastion.conf" #define CONFIG_PATH CONFIG_DIR "bastion.conf"
#define VERSION "@PROJECT_VERSION@"
#define GIT_HASH "@GIT_HASH@"
#define MAX_HOSTNAME_LENGTH 64 #define MAX_HOSTNAME_LENGTH 64
@ -17,7 +19,7 @@
#define SESSION_RECORDING_DIRECTORY_MODE S_IRUSR | S_IWUSR | S_IXUSR #define SESSION_RECORDING_DIRECTORY_MODE S_IRUSR | S_IWUSR | S_IXUSR
#endif #endif
char config_load(void); char config_load(const char *config_file);
int config_get_port(void); int config_get_port(void);
const char * config_get_key_dsa(void); const char * config_get_key_dsa(void);
const char * config_get_key_rsa(void); const char * config_get_key_rsa(void);

View file

@ -34,3 +34,6 @@ if (SESSION_RECORDING)
target_link_libraries(termplay bz2 curl lzma pthread z) target_link_libraries(termplay bz2 curl lzma pthread z)
install(TARGETS termplay DESTINATION bin) install(TARGETS termplay DESTINATION bin)
endif() endif()
# Build parg library for argument parsing
add_library(libparg parg/parg.c parg/parg.h)

1
external/parg vendored Submodule

@ -0,0 +1 @@
Subproject commit 97f3a075109ebace4f660fb341c6b99b2a4b092a