~sircmpwn/gmni-devel

Use strncpy to build TLS_CLIENT_HASH v1 APPLIED

dece: 3
 Use strncpy to build TLS_CLIENT_HASH
 Support TLS_CLIENT_SERIAL_NUMBER in CGI
 Support REMOTE_USER in CGI

 5 files changed, 39 insertions(+), 4 deletions(-)
Thanks!

To git@git.sr.ht:~sircmpwn/gmnisrv
   9f2481d..b9a9219  master -> master
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/gmni-devel/patches/23353/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH 1/3] Use strncpy to build TLS_CLIENT_HASH Export this patch

strncat on an uninitialized array leads to issues.
---
 src/serve.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/serve.c b/src/serve.c
index b2d114e..da17f96 100644
--- a/src/serve.c
+++ b/src/serve.c
@@ -215,7 +215,7 @@ serve_cgi(struct gmnisrv_client *client, const char *path,
				// +7 for "SHA256:" prefix
				// +1 for null char
				char hex_digest[32*2 + 7 + 1];
				strncat(hex_digest, "SHA256:", 8);
				strncpy(hex_digest, "SHA256:", 8);

				char *cur_pos = hex_digest + 7;
				for (int i = 0; i < 32; ++i) {
-- 
2.20.1

[PATCH 2/3] Support TLS_CLIENT_SERIAL_NUMBER in CGI Export this patch

---
 doc/gmnisrvini.scd |  3 +++
 src/serve.c        | 17 +++++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/doc/gmnisrvini.scd b/doc/gmnisrvini.scd
index 2c82b53..926529f 100644
--- a/doc/gmnisrvini.scd
+++ b/doc/gmnisrvini.scd
@@ -181,6 +181,9 @@ The following environment variables will be set:
|  *TLS_CLIENT_HASH*
:  SHA256:BD3A388021A92017B781504A3D24F324BF9DE11CE72606AB445D98A8EB00C5A8
:  Unique fingerprint of the client certificate.
|  *TLS_CLIENT_SERIAL_NUMBER*
:  717823108622037499122666796829184010024179612962
:  Serial number (decimal) of the client certificate.

\[1]: gemini://example.org/cgi-bin/foo.sh/bar?hello=world

diff --git a/src/serve.c b/src/serve.c
index da17f96..aa9a743 100644
--- a/src/serve.c
+++ b/src/serve.c
@@ -200,8 +200,7 @@ serve_cgi(struct gmnisrv_client *client, const char *path,

		// barebones client cert implementation
		// adapted from openssl(1)'s implementation
		// TODO: support REMOTE_USER, TLS_CLIENT_NOT_{BEFORE,AFTER},
		//       TLS_CLIENT_SERIAL_NUMBER
		// TODO: support REMOTE_USER, TLS_CLIENT_NOT_{BEFORE,AFTER}
		X509 *client_cert = SSL_get_peer_certificate(client->ssl);
		if (client_cert != NULL) {
			// 32 bytes because we're always using SHA256, but
@@ -226,6 +225,20 @@ serve_cgi(struct gmnisrv_client *client, const char *path,
				const char *error = "Out of memory";
				client_submit_response(client,
						GEMINI_STATUS_TEMPORARY_FAILURE, error, NULL);
				goto post_client_cert_parsing;
			}

			const ASN1_INTEGER *sn_asn = X509_get0_serialNumber(client_cert);
			BIGNUM *sn_bn = ASN1_INTEGER_to_BN(sn_asn, NULL);
			char *sn_dec = BN_bn2dec(sn_bn);
			BN_free(sn_bn);
			if (sn_dec != NULL) {
				setenv("TLS_CLIENT_SERIAL_NUMBER", sn_dec, 1);
				OPENSSL_free(sn_dec);
			} else {
				const char *error = "Invalid certificate serial number";
				client_submit_response(client,
						GEMINI_STATUS_CERTIFICATE_NOT_VALID, error, NULL);
			}
		}

-- 
2.20.1

[PATCH 3/3] Support REMOTE_USER in CGI Export this patch

---
 doc/gmnisrvini.scd |  3 +++
 src/serve.c        | 18 +++++++++++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/doc/gmnisrvini.scd b/doc/gmnisrvini.scd
index 926529f..5aed3e6 100644
--- a/doc/gmnisrvini.scd
+++ b/doc/gmnisrvini.scd
@@ -184,6 +184,9 @@ The following environment variables will be set:
|  *TLS_CLIENT_SERIAL_NUMBER*
:  717823108622037499122666796829184010024179612962
:  Serial number (decimal) of the client certificate.
|  *REMOTE_USER*
:  gemini user
:  Subject common name of the client certificate.

\[1]: gemini://example.org/cgi-bin/foo.sh/bar?hello=world

diff --git a/src/serve.c b/src/serve.c
index aa9a743..6ad7934 100644
--- a/src/serve.c
+++ b/src/serve.c
@@ -200,7 +200,7 @@ serve_cgi(struct gmnisrv_client *client, const char *path,

		// barebones client cert implementation
		// adapted from openssl(1)'s implementation
		// TODO: support REMOTE_USER, TLS_CLIENT_NOT_{BEFORE,AFTER}
		// TODO: support TLS_CLIENT_NOT_{BEFORE,AFTER}
		X509 *client_cert = SSL_get_peer_certificate(client->ssl);
		if (client_cert != NULL) {
			// 32 bytes because we're always using SHA256, but
@@ -239,8 +239,24 @@ serve_cgi(struct gmnisrv_client *client, const char *path,
				const char *error = "Invalid certificate serial number";
				client_submit_response(client,
						GEMINI_STATUS_CERTIFICATE_NOT_VALID, error, NULL);
				goto post_client_cert_parsing;
			}

			X509_NAME* subject_name = X509_get_subject_name(client_cert);
			int cn_index = X509_NAME_get_index_by_NID(subject_name,
					NID_commonName, -1);
			if (cn_index != -1) {
				ASN1_STRING *cn_asn = X509_NAME_ENTRY_get_data(
						X509_NAME_get_entry(subject_name, cn_index));
				unsigned char *cn = malloc(ASN1_STRING_length(cn_asn));
				ASN1_STRING_to_UTF8(&cn, cn_asn);
				setenv("REMOTE_USER", (char*) cn, 1);
				OPENSSL_free(cn);
			} else {
				setenv("REMOTE_USER", "", 1);
			}
		}
		post_client_cert_parsing:

		execlp(path, path, NULL);
		server_error("execlp: %s", strerror(errno));
-- 
2.20.1
Thanks!

To git@git.sr.ht:~sircmpwn/gmnisrv
   9f2481d..b9a9219  master -> master