commit - a709ddf5eb71e90a66cfd02bdaa9116c7f7ec3d6
commit + 3abf91b0b4a06e5d2f90e41f948e9c16478e23c7
blob - a84d157f539cb80428da9596ca4f3453c4b517ef
blob + a0c3e4bd140fce82fe5bf214db6c7c67fc115f7b
--- Makefile
+++ Makefile
y.tab.c: parse.y
${YACC} -b y -d parse.y
-SRCS = gmid.c iri.c utf8.c ex.c server.c sandbox.c mime.c puny.c utils.c
+SRCS = gmid.c iri.c utf8.c ex.c server.c sandbox.c mime.c puny.c utils.c log.c
OBJS = ${SRCS:.c=.o} lex.yy.o y.tab.o ${COMPAT}
gmid: ${OBJS}
blob - b2938f9fda6e1f4d8dd0c3a61980bf6f48d0cafb
blob + 08b8e6eaf8e94371c03717db9c5ebc3c77440f92
--- gmid.1
+++ gmid.1
.It Fl p Ar port
The port to listen on, by default 1965.
.It Fl v
-Increase the verbosity of the logs.
+Verbose mode.
+Multiple
+.Fl v
+options increase the verbosity.
.It Fl x Pa path
Enable execution of CGI scripts.
See the description of the
blob - a4f7868371625d6f8e6bbbb98ad75617eecace5d
blob + 023dd627341e053aae8fb166f6aaf3111aeb09cd
--- gmid.c
+++ gmid.c
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <limits.h>
-#include <netdb.h>
#include <pwd.h>
#include <signal.h>
-#include <stdarg.h>
#include <string.h>
-#include <openssl/pem.h>
-#include <openssl/x509.h>
-
#include "gmid.h"
volatile sig_atomic_t hupped;
struct vhost hosts[HOSTSLEN];
-int exfd, foreground, verbose, sock4, sock6;
+int exfd, sock4, sock6;
const char *config_path, *certs_dir, *hostname;
struct tls_config *tlsconf;
struct tls *ctx;
-
-void
-fatal(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
-
- if (foreground) {
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- } else
- vsyslog(LOG_DAEMON | LOG_CRIT, fmt, ap);
-
- va_end(ap);
- exit(1);
-}
-
-void
-logs(int priority, struct client *c,
- const char *fmt, ...)
-{
- char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
- char *fmted, *s;
- size_t len;
- int ec;
- va_list ap;
-
- if (foreground && !verbose) {
- if (priority == LOG_DEBUG || priority == LOG_INFO)
- return;
- }
-
- va_start(ap, fmt);
-
- if (c == NULL) {
- strncpy(hbuf, "<internal>", sizeof(hbuf));
- sbuf[0] = '\0';
- } else {
- len = sizeof(c->addr);
- ec = getnameinfo((struct sockaddr*)&c->addr, len,
- hbuf, sizeof(hbuf),
- sbuf, sizeof(sbuf),
- NI_NUMERICHOST | NI_NUMERICSERV);
- if (ec != 0)
- fatal("getnameinfo: %s", gai_strerror(ec));
- }
-
- if (vasprintf(&fmted, fmt, ap) == -1)
- fatal("vasprintf: %s", strerror(errno));
-
- if (foreground)
- fprintf(stderr, "%s:%s %s\n", hbuf, sbuf, fmted);
- else {
- if (asprintf(&s, "%s:%s %s", hbuf, sbuf, fmted) == -1)
- fatal("asprintf: %s", strerror(errno));
- syslog(priority | LOG_DAEMON, "%s", s);
- free(s);
- }
-
- free(fmted);
-
- va_end(ap);
-}
-
-/* strchr, but with a bound */
-static char *
-gmid_strnchr(char *s, int c, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len; ++i)
- if (s[i] == c)
- return &s[i];
- return NULL;
-}
-
-void
-log_request(struct client *c, char *meta, size_t l)
-{
- char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV], b[GEMINI_URL_LEN];
- char *t;
- size_t len;
- int ec;
-
- len = sizeof(c->addr);
- ec = getnameinfo((struct sockaddr*)&c->addr, len,
- hbuf, sizeof(hbuf),
- sbuf, sizeof(sbuf),
- NI_NUMERICHOST | NI_NUMERICSERV);
- if (ec != 0)
- fatal("getnameinfo: %s", gai_strerror(ec));
-
- if (c->iri.schema != NULL) {
- /* serialize the IRI */
- strlcpy(b, c->iri.schema, sizeof(b));
- strlcat(b, "://", sizeof(b));
-
- /* log the decoded host name, but if it was invalid
- * use the raw one. */
- if (*c->domain != '\0')
- strlcat(b, c->domain, sizeof(b));
- else
- strlcat(b, c->iri.host, sizeof(b));
-
- strlcat(b, "/", sizeof(b));
- strlcat(b, c->iri.path, sizeof(b)); /* TODO: sanitize UTF8 */
- if (*c->iri.query != '\0') { /* TODO: sanitize UTF8 */
- strlcat(b, "?", sizeof(b));
- strlcat(b, c->iri.query, sizeof(b));
- }
- } else {
- strlcpy(b, c->req, sizeof(b));
- }
- if ((t = gmid_strnchr(meta, '\r', l)) == NULL)
- t = meta + len;
-
- if (foreground)
- fprintf(stderr, "%s:%s GET %s %.*s\n", hbuf, sbuf, b,
- (int)(t - meta), meta);
- else
- syslog(LOG_INFO | LOG_DAEMON, "%s:%s GET %s %.*s",
- hbuf, sbuf, b, (int)(t - meta), meta);
-}
-
void
sig_handler(int sig)
{
hupped = sig == SIGHUP;
}
-void
-gen_certificate(const char *host, const char *certpath, const char *keypath)
-{
- BIGNUM e;
- EVP_PKEY *pkey;
- RSA *rsa;
- X509 *x509;
- X509_NAME *name;
- FILE *f;
- const char *org = "gmid";
-
- LOGN(NULL, "generating new certificate for %s (it could take a while)",
- host);
-
- if ((pkey = EVP_PKEY_new()) == NULL)
- fatal("couldn't create a new private key");
-
- if ((rsa = RSA_new()) == NULL)
- fatal("could'nt generate rsa");
-
- BN_init(&e);
- BN_set_word(&e, 17);
- if (!RSA_generate_key_ex(rsa, 4096, &e, NULL))
- fatal("couldn't generate a rsa key");
-
- if (!EVP_PKEY_assign_RSA(pkey, rsa))
- fatal("couldn't assign the key");
-
- if ((x509 = X509_new()) == NULL)
- fatal("couldn't generate the X509 certificate");
-
- ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
- X509_gmtime_adj(X509_get_notBefore(x509), 0);
- X509_gmtime_adj(X509_get_notAfter(x509), 315360000L); /* 10 years */
-
- if (!X509_set_pubkey(x509, pkey))
- fatal("couldn't set the public key");
-
- name = X509_get_subject_name(x509);
- if (!X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, org, -1, -1, 0))
- fatal("couldn't add N to cert");
- if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, host, -1, -1, 0))
- fatal("couldn't add CN to cert");
- X509_set_issuer_name(x509, name);
-
- if (!X509_sign(x509, pkey, EVP_sha256()))
- fatal("couldn't sign the certificate");
-
- if ((f = fopen(keypath, "w")) == NULL)
- fatal("fopen(%s): %s", keypath, strerror(errno));
- if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL))
- fatal("couldn't write private key");
- fclose(f);
-
- if ((f = fopen(certpath, "w")) == NULL)
- fatal("fopen(%s): %s", certpath, strerror(errno));
- if (!PEM_write_X509(f, x509))
- fatal("couldn't write cert");
- fclose(f);
-
- X509_free(x509);
- RSA_free(rsa);
-}
-
/* XXX: create recursively */
void
mkdirs(const char *path)
}
if (getuid() == 0)
- LOGW(NULL, "%s",
- "not a good idea to run a network daemon as root");
-}
-
-void
-usage(const char *me)
-{
- fprintf(stderr,
- "USAGE: %s [-fn] [-c config] | [-6h] [-d certs-dir] [-H host]"
- " [-p port] [-x cgi] [dir]",
- me);
+ log_warn(NULL, "not a good idea to run a network daemon as root");
}
static int
return listener_main();
}
+static void
+usage(const char *me)
+{
+ fprintf(stderr,
+ "USAGE: %s [-fn] [-c config] | [-6h] [-d certs-dir] [-H host]"
+ " [-p port] [-x cgi] [dir]",
+ me);
+}
+
static int
serve(int argc, char **argv, int *p)
{
return 1;
}
- LOGN(NULL, "serving %s on port %d", hosts[0].dir, conf.port);
+ log_notice(NULL, "serving %s on port %d", hosts[0].dir, conf.port);
}
/* setup tls before dropping privileges: we don't want user
break;
case 'f':
- foreground = 1;
+ conf.foreground = 1;
break;
case 'H':
break;
case 'v':
- verbose = 1;
+ conf.verbose++;
break;
case 'x':
if (config_path == NULL) {
configless = 1;
- foreground = 1;
+ conf.foreground = 1;
+ conf.prefork = 0;
+ conf.verbose++;
}
if (config_path != NULL && (argc > 0 || configless))
signal(SIGUSR2, sig_handler);
signal(SIGHUP, sig_handler);
- if (!foreground && !configless) {
+ if (!conf.foreground && !configless) {
if (daemon(1, 1) == -1)
fatal("daemon: %s", strerror(errno));
}
if (conf.ipv6)
sock6 = make_socket(conf.port, AF_INET6);
- if (configless) {
- conf.prefork = 0;
+ if (configless)
return serve(argc, argv, p);
- }
/* wait a sighup and reload the daemon */
for (;;) {
wait_sighup();
unblock_signals();
- LOGI(NULL, "reloading configuration %s", config_path);
+ log_info(NULL, "reloading configuration %s", config_path);
old_ipv6 = conf.ipv6;
old_port = conf.port;
blob - 51379fb849613a40b3ec715d74a73ad41908880f
blob + af829ba968a9fc8b2472ce6efd7403d4811d37ef
--- gmid.h
+++ gmid.h
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <syslog.h>
#include <tls.h>
#include <unistd.h>
#define DOMAIN_NAME_LEN (253+1)
#define LABEL_LEN (63+1)
-#define LOGE(c, fmt, ...) logs(LOG_ERR, c, fmt, __VA_ARGS__)
-#define LOGW(c, fmt, ...) logs(LOG_WARNING, c, fmt, __VA_ARGS__)
-#define LOGN(c, fmt, ...) logs(LOG_NOTICE, c, fmt, __VA_ARGS__)
-#define LOGI(c, fmt, ...) logs(LOG_INFO, c, fmt, __VA_ARGS__)
-#define LOGD(c, fmt, ...) logs(LOG_DEBUG, c, fmt, __VA_ARGS__)
-
struct location {
const char *match;
const char *lang;
};
struct conf {
+ /* from command line */
+ int foreground;
+ int verbose;
+
+ /* in the config */
int port;
int ipv6;
uint32_t protos;
};
/* gmid.c */
-__attribute__((format (printf, 1, 2)))
-__attribute__((__noreturn__))
-void fatal(const char*, ...);
-
-__attribute__((format (printf, 3, 4)))
-void logs(int, struct client*, const char*, ...);
-void log_request(struct client*, char*, size_t);
-
void sig_handler(int);
-void gen_certificate(const char*, const char*, const char*);
void mkdirs(const char*);
char *data_dir(void);
void load_local_cert(const char*, const char*);
void init_config(void);
void free_config(void);
void drop_priv(void);
-void usage(const char*);
/* provided by lex/yacc */
extern FILE *yyin;
int parse_portno(const char*);
void parse_conf(const char*);
+/* log.c */
+void fatal(const char*, ...)
+ __attribute__((format (printf, 1, 2)))
+ __attribute__((__noreturn__));
+
+#define LOG_ATTR_FMT __attribute__((format (printf, 2, 3)))
+void log_err(struct client*, const char*, ...) LOG_ATTR_FMT;
+void log_warn(struct client*, const char*, ...) LOG_ATTR_FMT;
+void log_notice(struct client*, const char*, ...) LOG_ATTR_FMT;
+void log_info(struct client*, const char*, ...) LOG_ATTR_FMT;
+void log_debug(struct client*, const char*, ...) LOG_ATTR_FMT;
+void log_request(struct client*, char*, size_t);
+
/* mime.c */
void init_mime(struct mime*);
void add_mime(struct mime*, const char*, const char*);
ssize_t filesize(int);
char *absolutify_path(const char*);
char *xstrdup(const char*);
+void gen_certificate(const char*, const char*, const char*);
#endif
blob - b28065cd5df384c3c9fa25fb454789ce99c458f2
blob + aa6c56ad10f6f2a0252f67c2d35cd396a6a68fff
--- puny.c
+++ puny.c
#define IBIAS 72
#define IN 128
+/* to make the linker happy */
+struct conf conf;
+
static int
adapt(int delta, int numpoints, int firsttime)
{
blob - 8a29ce505bfaecf01b6d65e0c7b73ee1d18d1b01
blob + 56f3d5567eb4c7251a812f3f20ee4776eea236b9
--- regress/Makefile
+++ regress/Makefile
./runtime
./iri_test
-puny-test: puny-test.o ../puny.o ../utf8.o ../utils.o
- ${CC} puny-test.o ../puny.o ../utf8.o ../utils.o -o puny-test
+puny-test: puny-test.o ../puny.o ../utf8.o ../utils.o ../log.o
+ ${CC} puny-test.o ../puny.o ../utf8.o ../utils.o ../log.o -o puny-test ${LDFLAGS}
iri_test: iri_test.o ../iri.o ../utf8.o
${CC} iri_test.o ../iri.o ../utf8.o -o iri_test
blob - b057baa6f4fa56e2455f4c6d4460294b556ba075
blob + 261515bb090302b4264dd9f7971f154835a7ec0d
--- server.c
+++ server.c
return FILE_MISSING;
if (fstat(*fd, &sb) == -1) {
- LOGN(c, "failed stat for %s: %s", path, strerror(errno));
+ log_notice(c, "failed stat for %s: %s", path, strerror(errno));
return FILE_MISSING;
}
load_file(struct pollfd *fds, struct client *c)
{
if ((c->len = filesize(c->fd)) == -1) {
- LOGE(c, "failed to get file size for %s: %s",
+ log_err(c, "failed to get file size for %s: %s",
c->iri.path, strerror(errno));
start_reply(fds, c, TEMP_FAILURE, "internal server error");
return;
if ((c->buf = mmap(NULL, c->len, PROT_READ, MAP_PRIVATE,
c->fd, 0)) == MAP_FAILED) {
- LOGW(c, "mmap: %s: %s", c->iri.path, strerror(errno));
+ log_err(c, "mmap: %s: %s", c->iri.path, strerror(errno));
start_reply(fds, c, TEMP_FAILURE, "internal server error");
return;
}
servname = tls_conn_servername(c->ctx);
if (!puny_decode(servname, c->domain, sizeof(c->domain), &parse_err)) {
- LOGI(c, "%s", parse_err);
+ log_info(c, "puny_decode: %s", parse_err);
goto err;
}
break;
}
- /* LOGD(c, "handshake: SNI: \"%s\"; decoded: \"%s\"; matched: \"%s\"", */
- /* servname != NULL ? servname : "(null)", */
- /* c->domain, */
- /* h->domain != NULL ? h->domain : "(null)"); */
+ log_debug(c, "handshake: SNI: \"%s\"; decoded: \"%s\"; matched: \"%s\"",
+ servname != NULL ? servname : "(null)",
+ c->domain,
+ h->domain != NULL ? h->domain : "(null)");
if (h->domain != NULL) {
c->host = h;
switch (tls_read(c->ctx, c->req, sizeof(c->req)-1)) {
case -1:
- LOGE(c, "tls_read: %s", tls_error(c->ctx));
+ log_err(c, "tls_read: %s", tls_error(c->ctx));
close_conn(fds, c);
return;
if (!trim_req_iri(c->req, &parse_err)
|| !parse_iri(c->req, &c->iri, &parse_err)
|| !puny_decode(c->iri.host, decoded, sizeof(decoded), &parse_err)) {
- LOGI(c, "iri parse error: %s", parse_err);
+ log_info(c, "iri parse error: %s", parse_err);
start_reply(fds, c, BAD_REQUEST, "invalid request");
return;
}
while (len > 0) {
switch (ret = tls_write(c->ctx, c->i, len)) {
case -1:
- LOGE(c, "tls_write: %s", tls_error(c->ctx));
+ log_err(c, "tls_write: %s", tls_error(c->ctx));
close_conn(fds, c);
return;
c->next = enter_handle_dirlist;
if ((c->dir = fdopendir(c->fd)) == NULL) {
- LOGE(c, "can't fdopendir(%d) (vhost:%s) %s: %s",
+ log_err(c, "fdopendir(%d) (vhost:%s) %s: %s",
c->fd, c->host->domain, c->iri.path, strerror(errno));
start_reply(fds, c, TEMP_FAILURE, "internal server error");
return;
errno = 0;
if ((d = readdir(c->dir)) == NULL) {
if (errno != 0)
- LOGE(c, "readdir: %s", strerror(errno));
+ log_err(c, "readdir: %s", strerror(errno));
return 0;
}
} while (!strcmp(d->d_name, "."));
blob - 6254deded503db7af5034c28829cef3a936237e5
blob + bd24b84af161f81fcda1ff105f58b1c2334173fa
--- utils.c
+++ utils.c
#include <errno.h>
#include <string.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
#include "gmid.h"
static sigset_t set;
err(1, "strdup");
return d;
}
+
+void
+gen_certificate(const char *host, const char *certpath, const char *keypath)
+{
+ BIGNUM e;
+ EVP_PKEY *pkey;
+ RSA *rsa;
+ X509 *x509;
+ X509_NAME *name;
+ FILE *f;
+ const char *org = "gmid";
+
+ log_notice(NULL,
+ "generating new certificate for %s (it could take a while)",
+ host);
+
+ if ((pkey = EVP_PKEY_new()) == NULL)
+ fatal("couldn't create a new private key");
+
+ if ((rsa = RSA_new()) == NULL)
+ fatal("could'nt generate rsa");
+
+ BN_init(&e);
+ BN_set_word(&e, 17);
+ if (!RSA_generate_key_ex(rsa, 4096, &e, NULL))
+ fatal("couldn't generate a rsa key");
+
+ if (!EVP_PKEY_assign_RSA(pkey, rsa))
+ fatal("couldn't assign the key");
+
+ if ((x509 = X509_new()) == NULL)
+ fatal("couldn't generate the X509 certificate");
+
+ ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
+ X509_gmtime_adj(X509_get_notBefore(x509), 0);
+ X509_gmtime_adj(X509_get_notAfter(x509), 315360000L); /* 10 years */
+
+ if (!X509_set_pubkey(x509, pkey))
+ fatal("couldn't set the public key");
+
+ name = X509_get_subject_name(x509);
+ if (!X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, org, -1, -1, 0))
+ fatal("couldn't add N to cert");
+ if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, host, -1, -1, 0))
+ fatal("couldn't add CN to cert");
+ X509_set_issuer_name(x509, name);
+
+ if (!X509_sign(x509, pkey, EVP_sha256()))
+ fatal("couldn't sign the certificate");
+
+ if ((f = fopen(keypath, "w")) == NULL)
+ fatal("fopen(%s): %s", keypath, strerror(errno));
+ if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL))
+ fatal("couldn't write private key");
+ fclose(f);
+
+ if ((f = fopen(certpath, "w")) == NULL)
+ fatal("fopen(%s): %s", certpath, strerror(errno));
+ if (!PEM_write_X509(f, x509))
+ fatal("couldn't write cert");
+ fclose(f);
+
+ X509_free(x509);
+ RSA_free(rsa);
+}