From ebabaa69c0a3ba992895c7a66729e81e0923d5f1 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Thu, 5 Apr 2018 17:53:27 +0200 Subject: Initial commit. Signed-off-by: Toni Uhlig --- AUTHORS | 0 ChangeLog | 0 Makefile.am | 1 + NEWS | 0 README | 0 autogen.sh | 9 +++++++ configure.ac | 12 +++++++++ src/Makefile.am | 5 ++++ src/log.c | 8 ++++++ src/log.h | 44 ++++++++++++++++++++++++++++++ src/log_colored.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/log_colored.h | 25 +++++++++++++++++ src/main.c | 35 ++++++++++++++++++++++++ src/server.c | 38 ++++++++++++++++++++++++++ src/server.h | 46 +++++++++++++++++++++++++++++++ src/server_ssh.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/server_ssh.h | 27 +++++++++++++++++++ src/socket.c | 30 +++++++++++++++++++++ src/socket.h | 19 +++++++++++++ src/utils.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.h | 8 ++++++ 21 files changed, 539 insertions(+) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 src/Makefile.am create mode 100644 src/log.c create mode 100644 src/log.h create mode 100644 src/log_colored.c create mode 100644 src/log_colored.h create mode 100644 src/main.c create mode 100644 src/server.c create mode 100644 src/server.h create mode 100644 src/server_ssh.c create mode 100644 src/server_ssh.h create mode 100644 src/socket.c create mode 100644 src/socket.h create mode 100644 src/utils.c create mode 100644 src/utils.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..48e9f68 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e +set -x + +aclocal +autoheader +automake --add-missing +autoconf diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..69ae2b1 --- /dev/null +++ b/configure.ac @@ -0,0 +1,12 @@ +AC_INIT(potd, 1.0, matzeton@googlemail.com) +AC_CONFIG_HEADERS([src/config.h]) +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE +AM_SILENT_RULES([yes]) +AM_MAINTAINER_MODE +AC_PROG_CC +AC_PROG_CC_STDC + +PKG_CHECK_MODULES([libssh], [libssh >= 0.7.3]) + +AC_OUTPUT(Makefile src/Makefile) diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..db612f1 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,5 @@ +AM_CFLAGS = -pedantic -Wall -std=gnu99 -D_GNU_SOURCE=1 +AM_LDFLAGS = -lssh + +sbin_PROGRAMS = potd +potd_SOURCES = main.c utils.c log.c log_colored.c socket.c server.c server_ssh.c diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..40ef5cb --- /dev/null +++ b/src/log.c @@ -0,0 +1,8 @@ +#include + +#include "log.h" + +log_open_cb log_open = NULL; +log_close_cb log_close = NULL; +log_fmt_cb log_fmt = NULL; +log_fmtex_cb log_fmtex = NULL; diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..3363395 --- /dev/null +++ b/src/log.h @@ -0,0 +1,44 @@ +#ifndef POTD_LOG_H +#define POTD_LOG_H 1 + +#include +#include +#include + +#define LOGMSG_MAXLEN 255 +#define LOG_SET_FUNCS(open_cb, close_cb, fmt_cb, fmtex_cb) \ + { \ + log_open = open_cb; log_close = close_cb; \ + log_fmt = fmt_cb; log_fmtex = fmtex_cb; \ + } +#define LOG_SET_FUNCS_VA(...) LOG_SET_FUNCS(__VA_ARGS__) +#define D(fmt, ...) log_fmt(DEBUG, fmt, __VA_ARGS__) +#define N(fmt, ...) log_fmt(NOTICE, fmt, __VA_ARGS__) +#define W(fmt, ...) log_fmt(WARNING, fmt, __VA_ARGS__) +#define E(fmt, ...) log_fmt(ERROR, fmt, __VA_ARGS__) +#define D2(fmt, ...) log_fmtex(DEBUG, __FILE__, __LINE__, fmt, __VA_ARGS__) +#define N2(fmt, ...) log_fmtex(NOTICE, __FILE__, __LINE__, fmt, __VA_ARGS__) +#define W2(fmt, ...) log_fmtex(WARNING, __FILE__, __LINE__, fmt, __VA_ARGS__) +#define E2(fmt, ...) log_fmtex(ERROR, __FILE__, __LINE__, fmt, __VA_ARGS__) +#define W_STRERR(msg) { if (errno) W2("%s failed: %s", msg, strerror(errno)); } +#define E_STRERR(msg) { if (errno) E2("%s failed: %s", msg, strerror(errno)); } +#define ABORT_ON_FATAL(expr, msg) \ + { errno = 0; if (expr) { E_STRERR(msg); abort(); } } + +typedef enum log_priority { + DEBUG = 0, NOTICE, WARNING, ERROR +} log_priority; + +typedef int (*log_open_cb) (void); +typedef void (*log_close_cb) (void); +typedef void (*log_fmt_cb) (log_priority prio, const char *fmt, ...); +typedef void (*log_fmtex_cb) (log_priority prio, const char *srcfile, + size_t line, const char *fmt, ...); + + +extern log_open_cb log_open; +extern log_close_cb log_close; +extern log_fmt_cb log_fmt; +extern log_fmtex_cb log_fmtex; + +#endif diff --git a/src/log_colored.c b/src/log_colored.c new file mode 100644 index 0000000..a8a26e3 --- /dev/null +++ b/src/log_colored.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +#include "log_colored.h" + + +int log_open_colored(void) +{ + if (!getenv("TERM")) { + fprintf(stderr, "%s\n", "Missing TERM variable in your environment."); + return 1; + } + if (!strstr(getenv("TERM"), "linux") + && !strstr(getenv("TERM"), "xterm")) + { + fprintf(stderr, "%s\n", "Unsupported TERM variable in your environment"); + return 1; + } + return 0; +} + +void log_close_colored(void) +{ + return; +} + +void log_fmt_colored(log_priority prio, const char *fmt, ...) +{ + char out[LOGMSG_MAXLEN+1] = {0}; + va_list arglist; + + assert(fmt); + va_start(arglist, fmt); + assert( vsnprintf(&out[0], LOGMSG_MAXLEN, fmt, arglist) >= 0 ); + va_end(arglist); + + switch (prio) { + case DEBUG: + printf("[DEBUG] %s\n", out); + break; + case NOTICE: + printf("[" GRN "NOTICE" RESET "] %s\n", out); + break; + case WARNING: + printf("[" YEL "WARNING" RESET "] %s\n", out); + break; + case ERROR: + printf("[" RED "ERROR" RESET "] %s\n", out); + break; + } +} + +void log_fmtex_colored(log_priority prio, const char *srcfile, + size_t line, const char *fmt, ...) +{ + char out[LOGMSG_MAXLEN+1] = {0}; + va_list arglist; + + assert(fmt); + va_start(arglist, fmt); + assert( vsnprintf(&out[0], LOGMSG_MAXLEN, fmt, arglist) >= 0 ); + va_end(arglist); + + switch (prio) { + case DEBUG: + printf("[DEBUG] %s.%lu: %s\n", srcfile, line, out); + break; + case NOTICE: + printf("[" GRN "NOTICE" RESET "] %s.%lu: %s\n", srcfile, line, out); + break; + case WARNING: + printf("[" YEL "WARNING" RESET "] %s.%lu: %s\n", srcfile, line, out); + break; + case ERROR: + printf("[" RED "ERROR" RESET "] %s.%lu: %s\n", srcfile, line, out); + break; + } +} diff --git a/src/log_colored.h b/src/log_colored.h new file mode 100644 index 0000000..c7c0014 --- /dev/null +++ b/src/log_colored.h @@ -0,0 +1,25 @@ +#ifndef POTD_LOG_COLORED +#define POTD_LOG_COLORED 1 + +#include "log.h" + +/* ANSI terminal color codes */ +#define RESET "\x1B[0m" +#define GRN "\x1B[32;1m" +#define YEL "\x1B[33;1m" +#define RED "\x1B[31;1;5m" +/* LOG_SET_FUNCS comfort */ +#define LOG_COLORED_FUNCS log_open_colored, log_close_colored, \ + log_fmt_colored, log_fmtex_colored + + +int log_open_colored(void); + +void log_close_colored(void); + +void log_fmt_colored(log_priority prio, const char *fmt, ...); + +void log_fmtex_colored(log_priority prio, const char *srcfile, + size_t line, const char *fmt, ...); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..7ccc404 --- /dev/null +++ b/src/main.c @@ -0,0 +1,35 @@ +#include "log.h" +#include "log_colored.h" +#include "server.h" +#include "server_ssh.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +int main(int argc, char *argv[]) +{ + static server_ctx srv = {0}; + + (void)argc; + (void)argv; + + LOG_SET_FUNCS_VA(LOG_COLORED_FUNCS); + N("%s (C) 2018 Toni Uhlig (%s)", PACKAGE_STRING, PACKAGE_BUGREPORT); + + ABORT_ON_FATAL( server_init_ctx(&srv, ssh_init_cb), + "Server initialisation" ); + server_validate_ctx(&srv); + + ABORT_ON_FATAL( socket_init_in(&srv.sock, "127.0.0.1", 2222), + "Socket initialisation" ); + ABORT_ON_FATAL( socket_bind_listen(&srv.sock), + "Socket bind and listen" ); + ABORT_ON_FATAL( srv.server_cbs.on_listen(&srv.server_dat), + "Socket on listen callback" ); + + D2("%s", "Server mainloop"); + ABORT_ON_FATAL( server_mainloop(&srv), + "Server mainloop" ); + return 0; +} diff --git a/src/server.c b/src/server.c new file mode 100644 index 0000000..61664c5 --- /dev/null +++ b/src/server.c @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "server.h" + + +server_ctx * +server_init_ctx(server_ctx *ctx, init_cb init_fn) +{ + if (!ctx) + ctx = (server_ctx *) malloc(sizeof(*ctx)); + assert(ctx); + + memset(ctx, 0, sizeof(*ctx)); + if (!init_fn(ctx)) + return NULL; + + return ctx; +} + +int server_validate_ctx(server_ctx *ctx) +{ + assert(ctx); + assert(ctx->server_cbs.on_connect && ctx->server_cbs.on_disconnect + && ctx->server_cbs.mainloop); + assert(ctx->server_cbs.on_free && ctx->server_cbs.on_listen + && ctx->server_cbs.on_shutdown); + return 0; +} + +int server_mainloop(server_ctx *ctx) +{ + while (1) { + sleep(1); + } + return 0; +} diff --git a/src/server.h b/src/server.h new file mode 100644 index 0000000..69c3ad7 --- /dev/null +++ b/src/server.h @@ -0,0 +1,46 @@ +#ifndef POTD_SERVER_H +#define POTD_SERVER_H 1 + +#include "socket.h" + +typedef struct server_data { + void *data; +} server_data; + +typedef struct server_session { + void *data; +} server_session; + +typedef int (*on_connect_cb) (struct server_data *data, struct server_session *ses); +typedef int (*on_disconnect_cb) (struct server_data *data, struct server_session *ses); +typedef int (*on_data_cb) (struct server_data *data, struct server_session *ses); +typedef int (*on_free_cb) (struct server_data *data); +typedef int (*on_listen_cb) (struct server_data *data); +typedef int (*on_shutdown_cb) (struct server_data *data); + +typedef struct server_callbacks { + on_connect_cb on_connect; + on_disconnect_cb on_disconnect; + on_data_cb mainloop; + on_free_cb on_free; + on_listen_cb on_listen; + on_shutdown_cb on_shutdown; +} server_callbacks; + +typedef struct server_ctx { + server_callbacks server_cbs; + server_data server_dat; + psocket sock; +} server_ctx; + +typedef int (*init_cb) (struct server_ctx *ctx); + + +server_ctx * +server_init_ctx(server_ctx *ctx, init_cb init_fn); + +int server_validate_ctx(server_ctx *ctx); + +int server_mainloop(server_ctx *ctx); + +#endif diff --git a/src/server_ssh.c b/src/server_ssh.c new file mode 100644 index 0000000..92d9454 --- /dev/null +++ b/src/server_ssh.c @@ -0,0 +1,77 @@ +#include +#include +#include + +#include "server_ssh.h" +#include "server.h" + +static void set_default_keys(ssh_bind sshbind, int rsa_already_set, + int dsa_already_set, int ecdsa_already_set); + + +int ssh_on_connect(struct server_data *data, struct server_session *ses) +{ + return 0; +} + +int ssh_on_disconnect(struct server_data *data, struct server_session *ses) +{ + return 0; +} + +int ssh_mainloop_cb(struct server_data *data, struct server_session *ses) +{ + return 0; +} + +int ssh_init_cb(struct server_ctx *ctx) +{ + ctx->server_cbs.on_connect = ssh_on_connect; + ctx->server_cbs.on_disconnect = ssh_on_disconnect; + ctx->server_cbs.mainloop = ssh_mainloop_cb; + ctx->server_cbs.on_free = ssh_free_cb; + ctx->server_cbs.on_listen = ssh_listen_cb; + ctx->server_cbs.on_shutdown = ssh_shutdown_cb; + + ssh_init(); + ssh_data *d = (ssh_data *) calloc(1, sizeof(*d)); + d->sshbind = ssh_bind_new(); + ctx->server_dat.data = d; + if (!d->sshbind) + return 1; + + set_default_keys(d->sshbind, 0, 0, 0); + return 0; +} + +int ssh_free_cb(struct server_data *data) +{ + return 0; +} + +int ssh_listen_cb(struct server_data *data) +{ + return 0; +} + +int ssh_shutdown_cb(struct server_data *data) +{ + return 0; +} + +static void set_default_keys(ssh_bind sshbind, int rsa_already_set, + int dsa_already_set, int ecdsa_already_set) +{ + if (!rsa_already_set) { + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, + "./ssh_host_rsa_key"); + } + if (!dsa_already_set) { + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, + "./ssh_host_dsa_key"); + } + if (!ecdsa_already_set) { + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, + "./ssh_host_ecdsa_key"); + } +} diff --git a/src/server_ssh.h b/src/server_ssh.h new file mode 100644 index 0000000..dc80645 --- /dev/null +++ b/src/server_ssh.h @@ -0,0 +1,27 @@ +#ifndef POTD_SERVER_SSH_H +#define POTD_SERVER_SSH_H 1 + +#include + +#include "server.h" + +typedef struct ssh_data { + ssh_bind sshbind; +} ssh_data; + + +int ssh_on_connect(struct server_data *data, struct server_session *ses); + +int ssh_on_disconnect(struct server_data *data, struct server_session *ses); + +int ssh_mainloop_cb(struct server_data *_data, struct server_session *ses); + +int ssh_init_cb(struct server_ctx *ctx); + +int ssh_free_cb(struct server_data *data); + +int ssh_listen_cb(struct server_data *data); + +int ssh_shutdown_cb(struct server_data *data); + +#endif diff --git a/src/socket.c b/src/socket.c new file mode 100644 index 0000000..99e4477 --- /dev/null +++ b/src/socket.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +#include "socket.h" + + +int socket_init_in(psocket *psocket, const char *listen_addr, unsigned int listen_port) +{ + struct in_addr addr = {0}; + + assert(psocket); + if (!inet_aton(listen_addr, &addr)) + return 1; + + psocket->sock.sin_family = AF_INET; + psocket->sock.sin_addr = addr; + psocket->sock.sin_port = htons(listen_port); + psocket->fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + return psocket->fd < 0; +} + +int socket_bind_listen(psocket *psocket) +{ + assert(psocket); + if (bind(psocket->fd, &psocket->sock, sizeof(psocket->sock)) < 0) + return 1; + return listen(psocket->fd, POTD_BACKLOG) < 0; +} diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..1b1a762 --- /dev/null +++ b/src/socket.h @@ -0,0 +1,19 @@ +#ifndef POTD_SOCKET_H +#define POTD_SOCKET_H 1 + +#include + +#define POTD_BACKLOG 3 + +typedef struct psocket { + int fd; + struct sockaddr_in sock; +} psocket; + + +int socket_init_in(psocket *psocket, const char *listen_addr, + unsigned int listen_port); + +int socket_bind_listen(psocket *psocket); + +#endif diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..5c86017 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +#define _POSIX_PATH_MAX 256 + + +void set_procname(char *arg0, const char *newname) +{ + memset(arg0, 0, _POSIX_PATH_MAX); + strncpy(arg0, newname, _POSIX_PATH_MAX); +} + +int daemonize(void) +{ + pid_t pid; + + /* Fork off the parent process */ + pid = fork(); + + /* An error occurred */ + if (pid < 0) + exit(EXIT_FAILURE); + + /* Success: Let the parent terminate */ + if (pid > 0) + exit(EXIT_SUCCESS); + + /* On success: The child process becomes session leader */ + if (setsid() < 0) + exit(EXIT_FAILURE); + + /* Catch, ignore and handle signals */ + //TODO: Implement a working signal handler */ + signal(SIGCHLD, SIG_IGN); + signal(SIGHUP, SIG_IGN); + + /* Fork off for the second time*/ + pid = fork(); + + /* An error occurred */ + if (pid < 0) + exit(EXIT_FAILURE); + + /* Success: Let the parent terminate */ + if (pid > 0) + exit(EXIT_SUCCESS); + + /* Set new file permissions */ + umask(0); + + /* Change the working directory to the root directory */ + /* or another appropriated directory */ + chdir("/"); + + /* Close all open file descriptors */ + int x; + for (x = sysconf(_SC_OPEN_MAX); x>=0; x--) + { + close (x); + } + + /* Open the log file */ + openlog ("firstdaemon", LOG_PID, LOG_DAEMON); + + return 0; +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..587bf25 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,8 @@ +#ifndef POTD_UTILS_H +#define POTD_UTILS_H 1 + +void set_procname(char *arg0, const char *newname); + +int daemonize(void); + +#endif -- cgit v1.2.3