commit 3abf91b0b4a06e5d2f90e41f948e9c16478e23c7 from: Omar Polo date: Sun Feb 07 15:30:28 2021 UTC improve logs management commit - a709ddf5eb71e90a66cfd02bdaa9116c7f7ec3d6 commit + 3abf91b0b4a06e5d2f90e41f948e9c16478e23c7 blob - a84d157f539cb80428da9596ca4f3453c4b517ef blob + a0c3e4bd140fce82fe5bf214db6c7c67fc115f7b --- Makefile +++ Makefile @@ -13,7 +13,7 @@ lex.yy.c: lex.l y.tab.c 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 @@ -86,7 +86,10 @@ Print the usage and exit. .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 @@ -19,23 +19,17 @@ #include #include #include -#include -#include #include #include -#include #include -#include -#include - #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; @@ -43,132 +37,7 @@ struct conf conf; 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, "", 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) { @@ -177,70 +46,6 @@ 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) @@ -490,17 +295,7 @@ drop_priv(void) } 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 @@ -528,6 +323,15 @@ spawn_listeners(int *p) 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) { @@ -556,7 +360,7 @@ 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 @@ -606,7 +410,7 @@ main(int argc, char **argv) break; case 'f': - foreground = 1; + conf.foreground = 1; break; case 'H': @@ -628,7 +432,7 @@ main(int argc, char **argv) break; case 'v': - verbose = 1; + conf.verbose++; break; case 'x': @@ -649,7 +453,9 @@ main(int argc, char **argv) if (config_path == NULL) { configless = 1; - foreground = 1; + conf.foreground = 1; + conf.prefork = 0; + conf.verbose++; } if (config_path != NULL && (argc > 0 || configless)) @@ -670,7 +476,7 @@ main(int argc, char **argv) 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)); } @@ -687,10 +493,8 @@ main(int argc, char **argv) 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 (;;) { @@ -709,7 +513,7 @@ main(int argc, char **argv) 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 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -57,12 +56,6 @@ #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; @@ -103,6 +96,11 @@ struct mime { }; struct conf { + /* from command line */ + int foreground; + int verbose; + + /* in the config */ int port; int ipv6; uint32_t protos; @@ -186,16 +184,7 @@ enum { }; /* 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*); @@ -205,7 +194,6 @@ void setup_tls(void); void init_config(void); void free_config(void); void drop_priv(void); -void usage(const char*); /* provided by lex/yacc */ extern FILE *yyin; @@ -217,6 +205,19 @@ void yyerror(const char*, ...); 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*); @@ -268,5 +269,6 @@ int ends_with(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 @@ -28,6 +28,9 @@ #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 @@ -7,8 +7,8 @@ all: puny-test testdata iri_test cert.pem ./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 @@ -197,7 +197,7 @@ check_path(struct client *c, const char *path, int *fd 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; } @@ -248,7 +248,7 @@ static void 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; @@ -256,7 +256,7 @@ load_file(struct pollfd *fds, struct client *c) 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; } @@ -345,7 +345,7 @@ handle_handshake(struct pollfd *fds, struct client *c) 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; } @@ -354,10 +354,10 @@ handle_handshake(struct pollfd *fds, struct client *c) 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; @@ -453,7 +453,7 @@ handle_open_conn(struct pollfd *fds, struct client *c) 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; @@ -469,7 +469,7 @@ handle_open_conn(struct pollfd *fds, struct client *c) 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; } @@ -605,7 +605,7 @@ send_file(struct pollfd *fds, struct client *c) 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; @@ -687,7 +687,7 @@ open_dir(struct pollfd *fds, struct client *c) 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; @@ -780,7 +780,7 @@ read_next_dir_entry(struct client *c) 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 @@ -17,6 +17,9 @@ #include #include +#include +#include + #include "gmid.h" static sigset_t set; @@ -108,3 +111,68 @@ xstrdup(const char *s) 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); +}