aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2018-04-05 17:53:27 +0200
committerToni Uhlig <matzeton@googlemail.com>2018-04-07 00:03:28 +0200
commitebabaa69c0a3ba992895c7a66729e81e0923d5f1 (patch)
tree39b4a5b90a4f51c98486e8a00898e983b8878a12
Initial commit.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--AUTHORS0
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am1
-rw-r--r--NEWS0
-rw-r--r--README0
-rwxr-xr-xautogen.sh9
-rw-r--r--configure.ac12
-rw-r--r--src/Makefile.am5
-rw-r--r--src/log.c8
-rw-r--r--src/log.h44
-rw-r--r--src/log_colored.c81
-rw-r--r--src/log_colored.h25
-rw-r--r--src/main.c35
-rw-r--r--src/server.c38
-rw-r--r--src/server.h46
-rw-r--r--src/server_ssh.c77
-rw-r--r--src/server_ssh.h27
-rw-r--r--src/socket.c30
-rw-r--r--src/socket.h19
-rw-r--r--src/utils.c74
-rw-r--r--src/utils.h8
21 files changed, 539 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AUTHORS
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/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
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