mirror of https://github.com/omar-polo/gmid.git
improve logs management
This commit is contained in:
parent
a709ddf5eb
commit
3abf91b0b4
2
Makefile
2
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}
|
||||
|
|
5
gmid.1
5
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
|
||||
|
|
236
gmid.c
236
gmid.c
|
@ -19,23 +19,17 @@
|
|||
#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;
|
||||
|
||||
|
@ -44,131 +38,6 @@ 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, "<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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
36
gmid.h
36
gmid.h
|
@ -28,7 +28,6 @@
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <tls.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -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
|
||||
|
|
3
puny.c
3
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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
26
server.c
26
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, "."));
|
||||
|
|
68
utils.c
68
utils.c
|
@ -17,6 +17,9 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue