From f3c4c0ac653fbb7bac28abee3bc7b0d2e1b9da11 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Wed, 22 Mar 2023 14:52:04 +0000 Subject: [PATCH] Add a global log configuration. This is the easiest and cleanest way to get logging into some of the fundamental APIs, such as the database and TLS APIs. We don't want to have to pass logging functions to those, but they can safely use the global logging configuration. --- TODO.txt | 41 +++++++---- src/Log.c | 45 ++++++++++-- src/Main.c | 140 +++++++++++++++++-------------------- src/Matrix.c | 10 +-- src/Routes/RouteRefresh.c | 9 ++- src/Routes/RouteRegister.c | 3 +- src/Telodendria.c | 21 +++--- src/TelodendriaConfig.c | 28 ++++---- src/Tls/TlsLibreSSL.c | 32 ++++++++- src/Uia.c | 6 +- src/include/Log.h | 11 ++- src/include/Matrix.h | 1 - src/include/Telodendria.h | 2 +- 13 files changed, 207 insertions(+), 142 deletions(-) diff --git a/TODO.txt b/TODO.txt index acaefa7..238afd0 100644 --- a/TODO.txt +++ b/TODO.txt @@ -6,52 +6,63 @@ Key: [ ] Not Started [x] Done [~] In Progress -[!] Won't Fix +[!] Won't Do Milestone: v0.3.0 ----------------- -[~] Stream API +[x] Stream API [x] Implementation [x] Convert all code that deals with I/O [!] Multi-output (proof of concept) [!] Memory streams (proof of concept) - [~] TLS - [ ] SOCKS + [x] TLS + [!] SOCKS [x] Move/convert UtilStreamCopy() - [ ] Io man page - [ ] Stream man page - [ ] Tls man page -[~] HTTP Client API +[x] HTTP Client API [x] Document HttpParseHeaders() - [ ] HttpClient man page - [ ] Uri man page [x] Test on other platforms [x] Option to pretty-print Json [x] Document JsonEncode() and JsonEncodeValue() -[ ] Update man page for td [x] Document Telodendria and Main -[ ] Document tt and http-debug-server [x] Simple command line tool to make matrix requests [x] Built on HTTP client API [x] http man page -[~] Simple command line tool for working with JSON +[x] Simple command line tool for working with JSON [x] Pretty-print Json [x] Query fields for use in shell scripts. [x] Encode user-provided JSON strings [x] json man page - [ ] Update man pages for tp and send-patch +[x] Global log object + - So we don't have to pass LogConfig around everywhere + - Also allows debug and error logging in other APIs [ ] Proper HTTP request router - Support regex matching - [ ] Move configuration to database [ ] Initial configuration [ ] If no config, create one-time use registration token that grants user admin privileges. [ ] /_telodendria/admin/config endpoint [ ] Refactor TelodendriaConfig to just Config (ConfigLock() and ConfigUnlock()) +[ ] Make 'listen' directive in config an array of objects + - Each object has port, threads, maxConnections + - If tls is given, it can be null, false, or an object with cert and key +[ ] Pass TLS certs and keys into HttpServer + +[ ] Documentation + [ ] Io + [ ] Stream + [ ] Tls + [ ] HttpClient + [ ] Uri + [ ] td + [ ] tt + [ ] http-debug-server + [ ] tp + [ ] send-patch + [ ] Log [~] Client-Server API [x] 4: Token-based user registration diff --git a/src/Log.c b/src/Log.c index f1188c1..cb0618a 100644 --- a/src/Log.c +++ b/src/Log.c @@ -45,6 +45,8 @@ struct LogConfig pthread_mutex_t lock; }; +LogConfig *globalConfig = NULL; + LogConfig * LogConfigCreate(void) { @@ -68,6 +70,17 @@ LogConfigCreate(void) return config; } +LogConfig * +LogConfigGlobal(void) +{ + if (!globalConfig) + { + globalConfig = LogConfigCreate(); + } + + return globalConfig; +} + void LogConfigFlagClear(LogConfig * config, int flags) { @@ -111,6 +124,11 @@ LogConfigFree(LogConfig * config) StreamClose(config->out); Free(config); + + if (config == globalConfig) + { + globalConfig = NULL; + } } void @@ -202,12 +220,11 @@ LogConfigUnindent(LogConfig * config) } void -Log(LogConfig * config, int level, const char *msg,...) +Logv(LogConfig * config, int level, const char *msg, va_list argp) { size_t i; int doColor; char indicator; - va_list argp; /* * Only proceed if we have a config and its log level is set to a @@ -232,9 +249,7 @@ Log(LogConfig * config, int level, const char *msg,...) { /* No further print logic is needed; syslog will handle it all * for us. */ - va_start(argp, msg); vsyslog(level, msg, argp); - va_end(argp); pthread_mutex_unlock(&config->lock); return; } @@ -345,12 +360,30 @@ Log(LogConfig * config, int level, const char *msg,...) StreamPutc(config->out, ' '); } - va_start(argp, msg); StreamVprintf(config->out, msg, argp); StreamPutc(config->out, '\n'); - va_end(argp); StreamFlush(config->out); pthread_mutex_unlock(&config->lock); } + +void +LogTo(LogConfig *config, int level, const char *fmt, ...) +{ + va_list argp; + + va_start(argp, fmt); + Logv(config, level, fmt, argp); + va_end(argp); +} + +extern void +Log(int level, const char *fmt, ...) +{ + va_list argp; + + va_start(argp, fmt); + Logv(LogConfigGlobal(), level, fmt, argp); + va_end(argp); +} diff --git a/src/Main.c b/src/Main.c index d4d303c..b6379df 100644 --- a/src/Main.c +++ b/src/Main.c @@ -63,7 +63,6 @@ typedef enum ArgFlag int main(int argc, char **argv) { - LogConfig *lc; int exit = EXIT_SUCCESS; /* Arg parsing */ @@ -90,17 +89,15 @@ main(int argc, char **argv) memset(&matrixArgs, 0, sizeof(matrixArgs)); - lc = LogConfigCreate(); - - if (!lc) + if (!LogConfigGlobal()) { printf("Fatal error: unable to allocate memory for logger.\n"); return EXIT_FAILURE; } - MemoryHook(TelodendriaMemoryHook, lc); + MemoryHook(TelodendriaMemoryHook, NULL); - TelodendriaPrintHeader(lc); + TelodendriaPrintHeader(); while ((opt = getopt(argc, argv, "f:Vvn")) != -1) { @@ -128,7 +125,7 @@ main(int argc, char **argv) if (flags & ARG_VERBOSE) { - LogConfigLevelSet(lc, LOG_DEBUG); + LogConfigLevelSet(LogConfigGlobal(), LOG_DEBUG); } if (flags & ARG_VERSION) @@ -138,7 +135,7 @@ main(int argc, char **argv) if (!configArg) { - Log(lc, LOG_ERR, "No configuration file specified."); + Log(LOG_ERR, "No configuration file specified."); exit = EXIT_FAILURE; goto finish; } @@ -153,25 +150,25 @@ main(int argc, char **argv) configFile = StreamOpen(configArg, "r"); if (!configFile) { - Log(lc, LOG_ERR, "Unable to open configuration file '%s' for reading.", configArg); + Log(LOG_ERR, "Unable to open configuration file '%s' for reading.", configArg); exit = EXIT_FAILURE; goto finish; } } - Log(lc, LOG_NOTICE, "Processing configuration file '%s'.", configArg); + Log(LOG_NOTICE, "Processing configuration file '%s'.", configArg); config = JsonDecode(configFile); StreamClose(configFile); if (!config) { - Log(lc, LOG_ERR, "Syntax error in configuration file."); + Log(LOG_ERR, "Syntax error in configuration file."); exit = EXIT_FAILURE; goto finish; } - tConfig = TelodendriaConfigParse(config, lc); + tConfig = TelodendriaConfigParse(config, LogConfigGlobal()); JsonFree(config); if (!tConfig) @@ -182,13 +179,13 @@ main(int argc, char **argv) if (flags & ARG_CONFIGTEST) { - Log(lc, LOG_INFO, "Configuration is OK."); + Log(LOG_INFO, "Configuration is OK."); goto finish; } if (!tConfig->logTimestamp || strcmp(tConfig->logTimestamp, "default") != 0) { - LogConfigTimeStampFormatSet(lc, tConfig->logTimestamp); + LogConfigTimeStampFormatSet(LogConfigGlobal(), tConfig->logTimestamp); } else { @@ -198,24 +195,24 @@ main(int argc, char **argv) if (tConfig->flags & TELODENDRIA_LOG_COLOR) { - LogConfigFlagSet(lc, LOG_FLAG_COLOR); + LogConfigFlagSet(LogConfigGlobal(), LOG_FLAG_COLOR); } else { - LogConfigFlagClear(lc, LOG_FLAG_COLOR); + LogConfigFlagClear(LogConfigGlobal(), LOG_FLAG_COLOR); } - LogConfigLevelSet(lc, flags & ARG_VERBOSE ? LOG_DEBUG : tConfig->logLevel); + LogConfigLevelSet(LogConfigGlobal(), flags & ARG_VERBOSE ? LOG_DEBUG : tConfig->logLevel); if (chdir(tConfig->dataDir) != 0) { - Log(lc, LOG_ERR, "Unable to change into data directory: %s.", strerror(errno)); + Log(LOG_ERR, "Unable to change into data directory: %s.", strerror(errno)); exit = EXIT_FAILURE; goto finish; } else { - Log(lc, LOG_DEBUG, "Changed working directory to: %s", tConfig->dataDir); + Log(LOG_DEBUG, "Changed working directory to: %s", tConfig->dataDir); } @@ -225,22 +222,22 @@ main(int argc, char **argv) if (!logFile) { - Log(lc, LOG_ERR, "Unable to open log file for appending."); + Log(LOG_ERR, "Unable to open log file for appending."); exit = EXIT_FAILURE; goto finish; } - Log(lc, LOG_INFO, "Logging to the log file. Check there for all future messages."); - LogConfigOutputSet(lc, logFile); + Log(LOG_INFO, "Logging to the log file. Check there for all future messages."); + LogConfigOutputSet(LogConfigGlobal(), logFile); } else if (tConfig->flags & TELODENDRIA_LOG_STDOUT) { - Log(lc, LOG_DEBUG, "Already logging to standard output."); + Log(LOG_DEBUG, "Already logging to standard output."); } else if (tConfig->flags & TELODENDRIA_LOG_SYSLOG) { - Log(lc, LOG_INFO, "Logging to the syslog. Check there for all future messages."); - LogConfigFlagSet(lc, LOG_FLAG_SYSLOG); + Log(LOG_INFO, "Logging to the syslog. Check there for all future messages."); + LogConfigFlagSet(LogConfigGlobal(), LOG_FLAG_SYSLOG); openlog("telodendria", LOG_PID | LOG_NDELAY, LOG_DAEMON); /* Always log everything, because the Log API will control what @@ -249,28 +246,27 @@ main(int argc, char **argv) } else { - Log(lc, LOG_ERR, "Unknown logging method in flags: '%d'", tConfig->flags); - Log(lc, LOG_ERR, "This is a programmer error; please report it."); + Log(LOG_ERR, "Unknown logging method in flags: '%d'", tConfig->flags); + Log(LOG_ERR, "This is a programmer error; please report it."); exit = EXIT_FAILURE; goto finish; } - Log(lc, LOG_DEBUG, "Configuration:"); - LogConfigIndent(lc); - Log(lc, LOG_DEBUG, "Listen On: %d", tConfig->listenPort); - Log(lc, LOG_DEBUG, "Server Name: %s", tConfig->serverName); - Log(lc, LOG_DEBUG, "Base URL: %s", tConfig->baseUrl); - Log(lc, LOG_DEBUG, "Identity Server: %s", tConfig->identityServer); - Log(lc, LOG_DEBUG, "Run As: %s:%s", tConfig->uid, tConfig->gid); - Log(lc, LOG_DEBUG, "Data Directory: %s", tConfig->dataDir); - Log(lc, LOG_DEBUG, "Threads: %d", tConfig->threads); - Log(lc, LOG_DEBUG, "Max Connections: %d", tConfig->maxConnections); - Log(lc, LOG_DEBUG, "Max Cache: %ld", tConfig->maxCache); - Log(lc, LOG_DEBUG, "Flags: %x", tConfig->flags); - LogConfigUnindent(lc); + Log(LOG_DEBUG, "Configuration:"); + LogConfigIndent(LogConfigGlobal()); + Log(LOG_DEBUG, "Listen On: %d", tConfig->listenPort); + Log(LOG_DEBUG, "Server Name: %s", tConfig->serverName); + Log(LOG_DEBUG, "Base URL: %s", tConfig->baseUrl); + Log(LOG_DEBUG, "Identity Server: %s", tConfig->identityServer); + Log(LOG_DEBUG, "Run As: %s:%s", tConfig->uid, tConfig->gid); + Log(LOG_DEBUG, "Data Directory: %s", tConfig->dataDir); + Log(LOG_DEBUG, "Threads: %d", tConfig->threads); + Log(LOG_DEBUG, "Max Connections: %d", tConfig->maxConnections); + Log(LOG_DEBUG, "Max Cache: %ld", tConfig->maxCache); + Log(LOG_DEBUG, "Flags: %x", tConfig->flags); + LogConfigUnindent(LogConfigGlobal()); /* Arguments to pass into the HTTP handler */ - matrixArgs.lc = lc; matrixArgs.config = tConfig; /* Bind the socket before possibly dropping permissions */ @@ -278,13 +274,13 @@ main(int argc, char **argv) tConfig->maxConnections, MatrixHttpHandler, &matrixArgs); if (!httpServer) { - Log(lc, LOG_ERR, "Unable to create HTTP server on port %d: %s", + Log(LOG_ERR, "Unable to create HTTP server on port %d: %s", tConfig->listenPort, strerror(errno)); exit = EXIT_FAILURE; goto finish; } - Log(lc, LOG_DEBUG, "Running as uid:gid: %d:%d.", getuid(), getgid()); + Log(LOG_DEBUG, "Running as uid:gid: %d:%d.", getuid(), getgid()); if (tConfig->uid && tConfig->gid) { @@ -293,18 +289,18 @@ main(int argc, char **argv) if (!userInfo || !groupInfo) { - Log(lc, LOG_ERR, "Unable to locate the user/group specified in the configuration."); + Log(LOG_ERR, "Unable to locate the user/group specified in the configuration."); exit = EXIT_FAILURE; goto finish; } else { - Log(lc, LOG_DEBUG, "Found user/group information using getpwnam() and getgrnam()."); + Log(LOG_DEBUG, "Found user/group information using getpwnam() and getgrnam()."); } } else { - Log(lc, LOG_DEBUG, "No user/group info specified in the config."); + Log(LOG_DEBUG, "No user/group info specified in the config."); } if (getuid() == 0) @@ -313,35 +309,35 @@ main(int argc, char **argv) { if (setgid(groupInfo->gr_gid) != 0 || setuid(userInfo->pw_uid) != 0) { - Log(lc, LOG_ERR, "Unable to set process uid/gid."); + Log(LOG_ERR, "Unable to set process uid/gid."); exit = EXIT_FAILURE; goto finish; } else { - Log(lc, LOG_DEBUG, "Set uid/gid to %s:%s.", tConfig->uid, tConfig->gid); + Log(LOG_DEBUG, "Set uid/gid to %s:%s.", tConfig->uid, tConfig->gid); } } else { - Log(lc, LOG_WARNING, "We are running as root, and we are not dropping to another user"); - Log(lc, LOG_WARNING, "because none was specified in the configuration file."); - Log(lc, LOG_WARNING, "This is probably a security issue."); + Log(LOG_WARNING, "We are running as root, and we are not dropping to another user"); + Log(LOG_WARNING, "because none was specified in the configuration file."); + Log(LOG_WARNING, "This is probably a security issue."); } } else { - Log(lc, LOG_WARNING, "Not setting root directory, because we are not root."); + Log(LOG_WARNING, "Not setting root directory, because we are not root."); if (tConfig->uid && tConfig->gid) { if (getuid() != userInfo->pw_uid || getgid() != groupInfo->gr_gid) { - Log(lc, LOG_WARNING, "Not running as the uid/gid specified in the configuration."); + Log(LOG_WARNING, "Not running as the uid/gid specified in the configuration."); } else { - Log(lc, LOG_DEBUG, "Running as the uid/gid specified in the configuration."); + Log(LOG_DEBUG, "Running as the uid/gid specified in the configuration."); } } } @@ -359,18 +355,16 @@ main(int argc, char **argv) if (!tConfig->maxCache) { - Log(lc, LOG_WARNING, "Database caching is disabled."); - Log(lc, LOG_WARNING, - "If this is not what you intended, check the config file"); - Log(lc, LOG_WARNING, - "and ensure that maxCache is a valid number of bytes."); + Log(LOG_WARNING, "Database caching is disabled."); + Log(LOG_WARNING, "If this is not what you intended, check the config file"); + Log(LOG_WARNING, "and ensure that maxCache is a valid number of bytes."); } matrixArgs.db = DbOpen(".", tConfig->maxCache); if (!matrixArgs.db) { - Log(lc, LOG_ERR, "Unable to open data directory as a database."); + Log(LOG_ERR, "Unable to open data directory as a database."); exit = EXIT_FAILURE; goto finish; } @@ -378,28 +372,28 @@ main(int argc, char **argv) cron = CronCreate(60 * 1000); /* 1-minute tick */ if (!cron) { - Log(lc, LOG_ERR, "Unable to set up job scheduler."); + Log(LOG_ERR, "Unable to set up job scheduler."); exit = EXIT_FAILURE; goto finish; } - Log(lc, LOG_DEBUG, "Registering jobs..."); + Log(LOG_DEBUG, "Registering jobs..."); CronEvery(cron, 30 * 60 * 1000, (JobFunc *) UiaCleanup, &matrixArgs); - Log(lc, LOG_NOTICE, "Starting job scheduler..."); + Log(LOG_NOTICE, "Starting job scheduler..."); CronStart(cron); - Log(lc, LOG_NOTICE, "Starting server..."); + Log(LOG_NOTICE, "Starting server..."); if (!HttpServerStart(httpServer)) { - Log(lc, LOG_ERR, "Unable to start HTTP server."); + Log(LOG_ERR, "Unable to start HTTP server."); exit = EXIT_FAILURE; goto finish; } - Log(lc, LOG_INFO, "Listening on port: %d", tConfig->listenPort); + Log(LOG_INFO, "Listening on port: %d", tConfig->listenPort); sigAction.sa_handler = TelodendriaSignalHandler; sigfillset(&sigAction.sa_mask); @@ -407,7 +401,7 @@ main(int argc, char **argv) if (sigaction(SIGINT, &sigAction, NULL) < 0) { - Log(lc, LOG_ERR, "Unable to install signal handler."); + Log(LOG_ERR, "Unable to install signal handler."); exit = EXIT_FAILURE; goto finish; } @@ -417,18 +411,18 @@ main(int argc, char **argv) HttpServerJoin(httpServer); finish: - Log(lc, LOG_NOTICE, "Shutting down..."); + Log(LOG_NOTICE, "Shutting down..."); if (httpServer) { HttpServerFree(httpServer); - Log(lc, LOG_DEBUG, "Freed HTTP Server."); + Log(LOG_DEBUG, "Freed HTTP Server."); } if (cron) { CronStop(cron); CronFree(cron); - Log(lc, LOG_DEBUG, "Stopped and freed job scheduler."); + Log(LOG_DEBUG, "Stopped and freed job scheduler."); } /* @@ -442,11 +436,9 @@ finish: DbClose(matrixArgs.db); - LogConfigTimeStampFormatSet(lc, NULL); TelodendriaConfigFree(tConfig); - - Log(lc, LOG_DEBUG, "Exiting with code '%d'.", exit); + Log(LOG_DEBUG, "Exiting with code '%d'.", exit); /* * Uninstall the memory hook because it uses the Log @@ -455,7 +447,7 @@ finish: */ MemoryHook(NULL, NULL); - LogConfigFree(lc); + LogConfigFree(LogConfigGlobal()); /* Standard error should never have been opened, but just in case * it was, this doesn't hurt anything. */ diff --git a/src/Matrix.c b/src/Matrix.c index 2d6cd2b..9b6f0a2 100644 --- a/src/Matrix.c +++ b/src/Matrix.c @@ -38,7 +38,6 @@ void MatrixHttpHandler(HttpServerContext * context, void *argp) { MatrixHttpHandlerArgs *args = (MatrixHttpHandlerArgs *) argp; - LogConfig *lc = args->lc; Stream *stream; HashMap *response = NULL; @@ -52,12 +51,10 @@ MatrixHttpHandler(HttpServerContext * context, void *argp) requestPath = HttpRequestPath(context); - Log(lc, LOG_INFO, "%s %s", + Log(LOG_INFO, "%s %s", HttpRequestMethodToString(HttpRequestMethodGet(context)), requestPath); - LogConfigIndent(lc); - HttpResponseStatus(context, HTTP_OK); HttpResponseHeader(context, "Server", "Telodendria/" TELODENDRIA_VERSION); @@ -78,7 +75,7 @@ MatrixHttpHandler(HttpServerContext * context, void *argp) HttpResponseStatus(context, HTTP_NO_CONTENT); HttpSendHeaders(context); - goto finish; + return; } pathParts = MATRIX_PATH_CREATE(); @@ -146,9 +143,6 @@ MatrixHttpHandler(HttpServerContext * context, void *argp) } MATRIX_PATH_FREE(pathParts); - -finish: - LogConfigUnindent(lc); } HashMap * diff --git a/src/Routes/RouteRefresh.c b/src/Routes/RouteRefresh.c index 3bf960a..10ef1ba 100644 --- a/src/Routes/RouteRefresh.c +++ b/src/Routes/RouteRefresh.c @@ -45,7 +45,6 @@ ROUTE_IMPL(RouteRefresh, args) char *deviceId; Db *db = args->matrixArgs->db; - LogConfig *lc = args->matrixArgs->lc; User *user = NULL; DbRef *rtRef = NULL; @@ -96,9 +95,9 @@ ROUTE_IMPL(RouteRefresh, args) if (!oAtRef) { - Log(lc, LOG_ERR, "Refresh token '%s' points to an access token that doesn't exist.", + Log(LOG_ERR, "Refresh token '%s' points to an access token that doesn't exist.", refreshToken); - Log(lc, LOG_WARNING, "This refresh token will be deleted."); + Log(LOG_WARNING, "This refresh token will be deleted."); HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); response = MatrixErrorCreate(M_UNKNOWN); @@ -114,9 +113,9 @@ ROUTE_IMPL(RouteRefresh, args) user = UserLock(db, JsonValueAsString(HashMapGet(DbJson(oAtRef), "user"))); if (!user) { - Log(lc, LOG_ERR, "Access token '%s' points to a user that doesn't exist.", + Log(LOG_ERR, "Access token '%s' points to a user that doesn't exist.", oldAccessToken); - Log(lc, LOG_WARNING, "This access token will be deleted."); + Log(LOG_WARNING, "This access token will be deleted."); HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); response = MatrixErrorCreate(M_UNKNOWN); diff --git a/src/Routes/RouteRegister.c b/src/Routes/RouteRegister.c index 6e55869..035e730 100644 --- a/src/Routes/RouteRegister.c +++ b/src/Routes/RouteRegister.c @@ -66,7 +66,6 @@ ROUTE_IMPL(RouteRegister, args) char *fullUsername; Db *db = args->matrixArgs->db; - LogConfig *lc = args->matrixArgs->lc; User *user = NULL; @@ -249,7 +248,7 @@ ROUTE_IMPL(RouteRegister, args) Free(loginInfo); } - Log(lc, LOG_INFO, "Registered user '%s'", UserGetName(user)); + Log(LOG_INFO, "Registered user '%s'", UserGetName(user)); UserUnlock(user); finish: diff --git a/src/Telodendria.c b/src/Telodendria.c index 8a6f868..14f50ae 100644 --- a/src/Telodendria.c +++ b/src/Telodendria.c @@ -67,9 +67,10 @@ const char void TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args) { - LogConfig *lc = (LogConfig *) args; char *action; + (void) args; + switch (a) { case MEMORY_ALLOCATE: @@ -89,7 +90,7 @@ TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args) break; } - Log(lc, a == MEMORY_BAD_POINTER ? LOG_WARNING : LOG_DEBUG, + Log(a == MEMORY_BAD_POINTER ? LOG_WARNING : LOG_DEBUG, "%s:%d: %s %lu bytes of memory at %p.", MemoryInfoGetFile(i), MemoryInfoGetLine(i), action, MemoryInfoGetSize(i), @@ -171,25 +172,25 @@ TelodendriaGenerateMemReport(void) } void -TelodendriaPrintHeader(LogConfig * lc) +TelodendriaPrintHeader(void) { size_t i; for (i = 0; i < TELODENDRIA_LOGO_HEIGHT; i++) { - Log(lc, LOG_INFO, "%s", TelodendriaLogo[i]); + Log(LOG_INFO, "%s", TelodendriaLogo[i]); } for (i = 0; i < TELODENDRIA_HEADER_HEIGHT; i++) { - Log(lc, LOG_INFO, "%s", TelodendriaHeader[i]); + Log(LOG_INFO, "%s", TelodendriaHeader[i]); } - Log(lc, LOG_INFO, "Telodendria v" TELODENDRIA_VERSION); - Log(lc, LOG_INFO, ""); - Log(lc, LOG_INFO, + Log(LOG_INFO, "Telodendria v" TELODENDRIA_VERSION); + Log(LOG_INFO, ""); + Log(LOG_INFO, "Copyright (C) 2023 Jordan Bancino <@jordan:bancino.net>"); - Log(lc, LOG_INFO, + Log(LOG_INFO, "Documentation/Support: https://telodendria.io"); - Log(lc, LOG_INFO, ""); + Log(LOG_INFO, ""); } diff --git a/src/TelodendriaConfig.c b/src/TelodendriaConfig.c index 4eba79d..67996c7 100644 --- a/src/TelodendriaConfig.c +++ b/src/TelodendriaConfig.c @@ -38,17 +38,17 @@ value = HashMapGet(config, key); \ if (!value) \ { \ - Log(lc, LOG_ERR, "Missing required " key " directive."); \ + Log(LOG_ERR, "Missing required " key " directive."); \ goto error; \ } \ if (JsonValueType(value) == JSON_NULL) \ { \ - Log(lc, LOG_ERR, "Missing value for " key " directive."); \ + Log(LOG_ERR, "Missing value for " key " directive."); \ goto error; \ } \ if (JsonValueType(value) != type) \ { \ - Log(lc, LOG_ERR, "Expected " key " to be of type " #type); \ + Log(LOG_ERR, "Expected " key " to be of type " #type); \ goto error; \ } @@ -61,14 +61,14 @@ { \ if (JsonValueType(value) != JSON_STRING) \ { \ - Log(lc, LOG_ERR, "Expected " key " to be of type JSON_STRING"); \ + Log(LOG_ERR, "Expected " key " to be of type JSON_STRING"); \ goto error; \ } \ into = StrDuplicate(JsonValueAsString(value)); \ } \ else \ { \ - Log(lc, LOG_INFO, "Using default value " #default " for " key "."); \ + Log(LOG_INFO, "Using default value " #default " for " key "."); \ into = default ? StrDuplicate(default) : NULL; \ } @@ -78,14 +78,14 @@ { \ if (JsonValueType(value) != JSON_INTEGER) \ { \ - Log(lc, LOG_ERR, "Expected " key " to be of type JSON_INTEGER"); \ + Log(LOG_ERR, "Expected " key " to be of type JSON_INTEGER"); \ goto error; \ } \ into = JsonValueAsInteger(value); \ } \ else \ { \ - Log(lc, LOG_INFO, "Using default value " #default " for " key "."); \ + Log(LOG_INFO, "Using default value " #default " for " key "."); \ into = default; \ } @@ -128,7 +128,7 @@ ConfigParseLog(LogConfig * lc, TelodendriaConfig * tConfig, HashMap * config) } else { - Log(lc, LOG_ERR, "Invalid value for log.output: '%s'.", str); + Log(LOG_ERR, "Invalid value for log.output: '%s'.", str); goto error; } @@ -156,7 +156,7 @@ ConfigParseLog(LogConfig * lc, TelodendriaConfig * tConfig, HashMap * config) } else { - Log(lc, LOG_ERR, "Invalid value for log.level: '%s'.", tConfig->logLevel); + Log(LOG_ERR, "Invalid value for log.level: '%s'.", tConfig->logLevel); goto error; } @@ -175,7 +175,7 @@ ConfigParseLog(LogConfig * lc, TelodendriaConfig * tConfig, HashMap * config) { if (JsonValueType(value) != JSON_BOOLEAN) { - Log(lc, LOG_ERR, "Expected type JSON_BOOLEAN for log.color."); + Log(LOG_ERR, "Expected type JSON_BOOLEAN for log.color."); goto error; } @@ -222,11 +222,11 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc) } else { - Log(lc, LOG_WARNING, "Base URL not specified. Assuming it's 'https://%s'.", tConfig->serverName); + Log(LOG_WARNING, "Base URL not specified. Assuming it's 'https://%s'.", tConfig->serverName); tConfig->baseUrl = Malloc(strlen(tConfig->serverName) + 10); if (!tConfig->baseUrl) { - Log(lc, LOG_ERR, "Error allocating memory for default config value 'baseUrl'."); + Log(LOG_ERR, "Error allocating memory for default config value 'baseUrl'."); goto error; } @@ -247,8 +247,8 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc) } else { - Log(lc, LOG_ERR, "Config directive 'runAs' should be a JSON object"); - Log(lc, LOG_ERR, "that contains a 'uid' and 'gid'."); + Log(LOG_ERR, "Config directive 'runAs' should be a JSON object"); + Log(LOG_ERR, "that contains a 'uid' and 'gid'."); goto error; } } diff --git a/src/Tls/TlsLibreSSL.c b/src/Tls/TlsLibreSSL.c index f91b60c..e06f949 100644 --- a/src/Tls/TlsLibreSSL.c +++ b/src/Tls/TlsLibreSSL.c @@ -26,6 +26,8 @@ #if TLS_IMPL == TLS_LIBRESSL #include +#include + #include /* LibreSSL TLS */ typedef struct LibreSSLCookie @@ -77,6 +79,11 @@ TlsInitClient(int fd, const char *serverName) error: if (cookie->ctx) { + if (tls_error(cookie->ctx)) + { + Log(LOG_ERR, "TlsInitClient(): %s", tls_error(cookie->ctx)); + } + tls_free(cookie->ctx); } @@ -135,11 +142,20 @@ TlsInitServer(int fd, const char *crt, const char *key) error: if (cookie->ctx) { + if (tls_error(cookie->ctx)) + { + Log(LOG_ERR, "TlsInitServer(): %s", tls_error(cookie->ctx)); + } tls_free(cookie->ctx); } if (cookie->cctx) { + if (tls_error(cookie->cctx)) + { + Log(LOG_ERR, "TlsInitServer(): %s", tls_error(cookie->cctx)); + } + tls_free(cookie->cctx); } @@ -157,16 +173,28 @@ ssize_t TlsRead(void *cookie, void *buf, size_t nBytes) { LibreSSLCookie *tls = cookie; + ssize_t ret = tls_read(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes); - return tls_read(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes); + if (ret == -1) + { + Log(LOG_ERR, "TlsRead(): %s", tls_error(tls->cctx ? tls->cctx : tls->ctx)); + } + + return ret; } ssize_t TlsWrite(void *cookie, void *buf, size_t nBytes) { LibreSSLCookie *tls = cookie; + ssize_t ret = tls_write(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes); - return tls_write(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes); + if (ret == -1) + { + Log(LOG_ERR, "TlsWrite(): %s", tls_error(tls->cctx ? tls->cctx : tls->ctx)); + } + + return ret; } int diff --git a/src/Uia.c b/src/Uia.c index e0e460a..8f0b748 100644 --- a/src/Uia.c +++ b/src/Uia.c @@ -491,7 +491,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args) Array *sessions = DbList(args->db, 1, "user_interactive"); size_t i; - Log(args->lc, LOG_DEBUG, "User Interactive Auth sessions: %lu", + Log(LOG_DEBUG, "User Interactive Auth sessions: %lu", ArraySize(sessions)); for (i = 0; i < ArraySize(sessions); i++) { @@ -502,7 +502,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args) if (!ref) { - Log(args->lc, LOG_ERR, "Unable to lock uia %s for inspection.", + Log(LOG_ERR, "Unable to lock uia %s for inspection.", session); continue; } @@ -515,7 +515,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args) { DbUnlock(args->db, ref); DbDelete(args->db, 2, "user_interactive", session); - Log(args->lc, LOG_DEBUG, "Deleted session %s", session); + Log(LOG_DEBUG, "Deleted session %s", session); } DbUnlock(args->db, ref); diff --git a/src/include/Log.h b/src/include/Log.h index 932e894..f1a39b9 100644 --- a/src/include/Log.h +++ b/src/include/Log.h @@ -39,6 +39,9 @@ typedef struct LogConfig LogConfig; extern LogConfig * LogConfigCreate(void); +extern LogConfig * + LogConfigGlobal(void); + extern void LogConfigFree(LogConfig *); @@ -67,6 +70,12 @@ extern void LogConfigTimeStampFormatSet(LogConfig *, char *); extern void - Log(LogConfig *, int, const char *,...); + Logv(LogConfig *, int, const char *, va_list); + +extern void + LogTo(LogConfig *, int, const char *,...); + +extern void + Log(int, const char *, ...); #endif diff --git a/src/include/Matrix.h b/src/include/Matrix.h index 98d0f4a..a07f559 100644 --- a/src/include/Matrix.h +++ b/src/include/Matrix.h @@ -69,7 +69,6 @@ typedef enum MatrixError typedef struct MatrixHttpHandlerArgs { - LogConfig *lc; TelodendriaConfig *config; Db *db; } MatrixHttpHandlerArgs; diff --git a/src/include/Telodendria.h b/src/include/Telodendria.h index dde0a39..50f452d 100644 --- a/src/include/Telodendria.h +++ b/src/include/Telodendria.h @@ -46,6 +46,6 @@ extern void TelodendriaGenerateMemReport(void); extern void - TelodendriaPrintHeader(LogConfig *); + TelodendriaPrintHeader(void); #endif