diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-04-05 17:53:27 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-04-07 00:03:28 +0200 |
commit | ebabaa69c0a3ba992895c7a66729e81e0923d5f1 (patch) | |
tree | 39b4a5b90a4f51c98486e8a00898e983b8878a12 |
Initial commit.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | AUTHORS | 0 | ||||
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 0 | ||||
-rwxr-xr-x | autogen.sh | 9 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/log.c | 8 | ||||
-rw-r--r-- | src/log.h | 44 | ||||
-rw-r--r-- | src/log_colored.c | 81 | ||||
-rw-r--r-- | src/log_colored.h | 25 | ||||
-rw-r--r-- | src/main.c | 35 | ||||
-rw-r--r-- | src/server.c | 38 | ||||
-rw-r--r-- | src/server.h | 46 | ||||
-rw-r--r-- | src/server_ssh.c | 77 | ||||
-rw-r--r-- | src/server_ssh.h | 27 | ||||
-rw-r--r-- | src/socket.c | 30 | ||||
-rw-r--r-- | src/socket.h | 19 | ||||
-rw-r--r-- | src/utils.c | 74 | ||||
-rw-r--r-- | src/utils.h | 8 |
21 files changed, 539 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ChangeLog 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/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 <stdio.h> + +#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 <stdlib.h> +#include <string.h> +#include <errno.h> + +#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 <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> + +#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 <stdlib.h> +#include <string.h> +#include <assert.h> + +#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 <stdlib.h> +#include <libssh/callbacks.h> +#include <libssh/server.h> + +#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 <libssh/server.h> + +#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 <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <assert.h> + +#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 <netinet/in.h> + +#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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <syslog.h> + +#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 |