Added argument parsing with libparg, along with usefull running modes
This commit is contained in:
parent
a6f8d1da2a
commit
b372795ac7
8 changed files with 113 additions and 26 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||||
|
|
|
@ -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}")
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
116
bastion/main.c
116
bastion/main.c
|
@ -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 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
|
// 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:
|
||||||
/* Remove the SIGCHLD handler inherited from parent. */
|
if (!dont_fork) {
|
||||||
sa.sa_handler = SIG_DFL;
|
/* Remove the SIGCHLD handler inherited from parent. */
|
||||||
sigaction(SIGCHLD, &sa, NULL);
|
sa.sa_handler = SIG_DFL;
|
||||||
|
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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
3
external/CMakeLists.txt
vendored
3
external/CMakeLists.txt
vendored
|
@ -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
1
external/parg
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 97f3a075109ebace4f660fb341c6b99b2a4b092a
|
Reference in a new issue