commit - 9833f63a2064eadd4c4cf2061124d5131613425f
commit + 3d1ff5c2df0dd3ee4fd3dad597ea421dbc9ab26c
blob - 338a860e245c0825b3f31415366d9daf45e0fec7
blob + 20824e63b2355b7204e92a3d14dd59a15808a677
--- Makefile
+++ Makefile
$(INSTALL) -d -m 755 -o root $(MAN)/man8
$(INSTALL) -d -m 750 -o root $(CONFDIR)
$(INSTALL) -d -m 755 -o root $(GEMINIDIR)
+ $(INSTALL) -d -m 755 -o _twind -g _twind $(GEMINIDIR)/logs
$(INSTALL) -m 644 -o root twind.8 $(MAN)/man8
$(INSTALL) -m 755 -o root twind $(SBIN)
blob - c8df8c1cde601d1c43bd25de8299c5ea99716b6e
blob + 264f82269384d4b7fee7add1d3b756432256ccf8
--- log.c
+++ log.c
#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <time.h>
#include "log.h"
+#include "twind.h"
+#define MAXLOGLINE 1024
+
static int debug;
static int verbose;
static const char *log_procname;
va_end(ap);
exit(1);
}
+
+void
+open_twind_logs(void)
+{
+ if ((access_fd = open(_PATH_TWIND_ACCESS_LOG, O_WRONLY|O_APPEND|O_CREAT, 0644))
+ == -1)
+ fatalx("Cannot open access log: %s", _PATH_TWIND_ACCESS_LOG);
+
+ if ((error_fd = open(_PATH_TWIND_ERROR_LOG, O_WRONLY|O_APPEND|O_CREAT, 0644))
+ == -1)
+ fatalx("Cannot open error log: %s", _PATH_TWIND_ACCESS_LOG);
+
+ return;
+}
+
+void
+close_twind_logs(void)
+{
+ close(access_fd);
+ close(error_fd);
+}
+
+void
+log_access(const struct client_connection *cc, const char *fmt, ...)
+{
+ struct tm tm;
+ time_t t;
+
+ t = time(NULL);
+ tm = *localtime(&t);
+
+ user_log(0, "%s - - [%d/%d/%d:%d:%d:%d %s] %s", cc->client_addr,
+ tm.tm_mday, tm.tm_mon, tm.tm_year+1900,
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tm.tm_zone, fmt);
+}
+
+void
+log_error(const struct client_connection *cc, const char *fmt, ...)
+{
+ struct tm tm;
+ time_t t;
+
+ t = time(NULL);
+ tm = *localtime(&t);
+
+ user_log(1, "[%d/%d/%d:%d:%d:%d %s] [error] [client %s] %s",
+ tm.tm_mday, tm.tm_mon, tm.tm_year+1900,
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tm.tm_zone,
+ cc->client_addr,
+ fmt);
+}
+
+void
+user_log(int target, const char *fmt, ...)
+{
+ va_list ap;
+ int fd = -1;
+
+ va_start(ap, fmt);
+ if (target == 0)
+ fd = access_fd;
+ else if (target == 1)
+ fd = error_fd;
+ else {
+ log_warn("Non-existent user log target");
+ return;
+ }
+
+ vdprintf(fd, fmt, ap);
+ dprintf(fd, "\n");
+
+ va_end(ap);
+}
blob - 6d100a48988fc5bde78793af99c23abcf20445f5
blob + 496672085297e44af8d752fe6813ac15150ba64e
--- twind.c
+++ twind.c
log_init(debug_flag, LOG_DAEMON);
log_setverbose(verbose_flag);
+ open_twind_logs();
+
#ifdef __OpenBSD__
if (pledge("stdio inet dns proc rpath", NULL) == -1)
fatalx("pledge");
if (sub_pid == -1) {
if (errno == ECHILD) {
/* All sub processes are terminated */
+ close_twind_logs();
log_debug("twind turns to dust");
exit(0);
} else {
struct sockaddr_storage addr;
struct sockaddr_in clientaddr;
struct sockaddr_in6 clientaddr6;
+ struct client_connection *cc;
char str[INET6_ADDRSTRLEN];
pthread_t thread_id;
- SSL *ssl_peer;
socklen_t len = sizeof(addr);
int ret, ssl_err;
if (ret < 0)
fatalx("Error when accepting connection");
+ if ((cc = calloc(1, sizeof(struct client_connection))) == NULL)
+ fatalx("Cannot allocate memory for client structure");
+
getpeername(ret, (struct sockaddr *)&clientaddr, &len);
if (clientaddr.sin_family == AF_INET) {
- if (inet_ntop(AF_INET, &clientaddr.sin_addr, str, sizeof(str)))
+ if (inet_ntop(AF_INET, &clientaddr.sin_addr, cc->client_addr, sizeof(str)))
log_info("Connection from %s on Port %d",
- str, ntohs(clientaddr.sin_port));
+ cc->client_addr, ntohs(clientaddr.sin_port));
} else if (clientaddr.sin_family == AF_INET6) {
getpeername(ret, (struct sockaddr *)&clientaddr6, &len);
- if (inet_ntop(AF_INET6, &clientaddr6.sin6_addr, str, sizeof(str)))
+ if (inet_ntop(AF_INET6, &clientaddr6.sin6_addr, cc->client_addr, sizeof(str)))
log_info("Connection from %s on Port %d",
- str, ntohs(clientaddr6.sin6_port));
+ cc->client_addr, ntohs(clientaddr6.sin6_port));
}
- if ((ssl_peer = SSL_new(sslctx)) == NULL) {
+ if ((cc->ssl_peer = SSL_new(sslctx)) == NULL) {
log_warn("Creating new TLS structure failed");
+ free(cc);
close(ret);
continue;
}
- if (SSL_set_fd(ssl_peer, ret) == 0) {
+ if (SSL_set_fd(cc->ssl_peer, ret) == 0) {
log_warn("TLS cannot set file descriptor");
- SSL_free(ssl_peer);
+ SSL_free(cc->ssl_peer);
+ free(cc);
close(ret);
continue;
}
- ssl_err = SSL_accept(ssl_peer);
+ ssl_err = SSL_accept(cc->ssl_peer);
if (ssl_err < 0) {
ERR_print_errors_fp(stderr);
log_warn("Fatal TLS error. Cannot accept TLS connection");
- SSL_shutdown(ssl_peer);
- SSL_free(ssl_peer);
+ SSL_shutdown(cc->ssl_peer);
+ SSL_free(cc->ssl_peer);
+ free(cc);
close(ret);
continue;
} else if (ssl_err == 0) {
log_warn("TLS handshake not successful");
- SSL_shutdown(ssl_peer);
- SSL_free(ssl_peer);
+ SSL_shutdown(cc->ssl_peer);
+ SSL_free(cc->ssl_peer);
+ free(cc);
close(ret);
continue;
}
- log_debug("SSL connection using %s\n", SSL_get_cipher (ssl_peer));
+ log_debug("SSL connection using %s\n", SSL_get_cipher(cc->ssl_peer));
- if (pthread_create(&thread_id, NULL, main_request_handler, ((void*)ssl_peer))
+ if (pthread_create(&thread_id, NULL, main_request_handler, ((void*)cc))
!= 0) {
log_warn("Cannot create handling thread");
return -1;
pthread_join(thread_id, NULL);
- SSL_shutdown(ssl_peer);
- SSL_free(ssl_peer);
+ SSL_shutdown(cc->ssl_peer);
+ SSL_free(cc->ssl_peer);
+ free(cc);
close(ret);
}
void *
main_request_handler(void *argp)
{
- SSL *ssl_peer = (SSL*)argp;
+ struct client_connection *cc = (struct client_connection *)argp;
char finalpath[MAXREQLEN];
char temp[MAXREQLEN];
char request[MAXREQLEN];
memset(request, 0, sizeof(request));
memset(temp, 0, sizeof(temp));
- receive_gemini_request(ssl_peer, request);
+ receive_gemini_request(cc->ssl_peer, request);
ret = get_path_from_request(request, finalpath);
if (ret == -1) { /* Malformed request */
- send_non_success_response(ssl_peer, STATUS_BAD_REQUEST);
+ log_error(cc, "Malformed request");
+ send_non_success_response(cc->ssl_peer, STATUS_BAD_REQUEST);
return NULL;
} else if (ret == -2) { /* 404 */
- send_non_success_response(ssl_peer, STATUS_NOT_FOUND);
+ log_error(cc, "Request file not found");
+ send_non_success_response(cc->ssl_peer, STATUS_NOT_FOUND);
return NULL;
}
log_debug("Cannot get MIME type for %s", ext);
}
- if (send_response(ssl_peer, STATUS_SUCCESS, finalpath, mime) < 0) {
+ log_access(cc, finalpath);
+
+ if (send_response(cc->ssl_peer, STATUS_SUCCESS, finalpath, mime) < 0) {
log_warn("Sending response to client failed");
return NULL;
}
blob - cb93f4a30e0baa7e6ad993f3793bb5d472bc9836
blob + 04544300ea5a27dd7c3abc7466ea3261042fb118
--- twind.h
+++ twind.h
#ifndef _TWIND_H
#define _TWIND_H
+#include <netinet/in.h>
+
#include <openssl/ssl.h>
#define VERSION "2021.a"
#define MAXREQLEN 1025
+#define _PATH_TWIND_ACCESS_LOG "logs/access.log"
+#define _PATH_TWIND_ERROR_LOG "logs/error.log"
-/* gemini.c */
-int check_gemini_file(const char *);
-int send_response(SSL*, int, const char *, const char *);
-int send_non_success_response(SSL*, int);
+int access_fd;
+int error_fd;
-/* request.c */
-int get_path_from_request(char *, char *);
-
-/* mime.c */
-char* get_file_extension(const char*);
-char* get_mime_type(const char *);
-
-/* util.c */
-void* xmalloc(size_t);
-char* xstrdup(const char *);
-size_t strlcpy(char *, const char *, size_t);
-
enum status_codes {
STATUS_INPUT = 10,
STATUS_SENSITIVE_INPUT = 11,
STATUS_CERT_NOT_VALID = 62,
};
+struct client_connection {
+ SSL *ssl_peer;
+ char client_addr[INET6_ADDRSTRLEN];
+};
+
+/* gemini.c */
+int check_gemini_file(const char *);
+int send_response(SSL*, int, const char *, const char *);
+int send_non_success_response(SSL*, int);
+
+/* request.c */
+int get_path_from_request(char *, char *);
+
+/* mime.c */
+char* get_file_extension(const char*);
+char* get_mime_type(const char *);
+
+/* util.c */
+void* xmalloc(size_t);
+char* xstrdup(const char *);
+size_t strlcpy(char *, const char *, size_t);
+
+/* log.c */
+void open_twind_logs(void);
+void close_twind_logs(void);
+void log_access(const struct client_connection *, const char *, ...);
+void log_error(const struct client_connection *, const char *, ...);
+void user_log(int, const char *, ...);
+
#endif