Commit Diff


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 <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;
 
@@ -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, "<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;
blob - 51379fb849613a40b3ec715d74a73ad41908880f
blob + af829ba968a9fc8b2472ce6efd7403d4811d37ef
--- gmid.h
+++ 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
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 <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);
+}