Notes on Gemserv CGI handling

The Common Gateway Interface (CGI) is a standard that defines how servers interact with external programs to generate responses to server requests. Some Gemini servers implement it to some degree, though in spirit more than in detail, because Gemini is a lot less complex than HTTP that CGI was designed for.

Gemserv has a boolean option 'cgi' that enables CGI execution. This means that any request to an executable file will result in that file being executed and the output returned to the client.

The option 'cgipath' allows you to limit CGI executables to the given directory. This should be defined as the *absolute* filesystem path to the executable (e.g. /home/kevin/gemfiles/cgi-bin). If 'cgi' is true, but you don't set this option, then *any* file that is executable could be run by a request.

Here's an example Bash script that, if marked executable, will return some server information generated from /proc values. I have organised it using a heredoc so that the Gemini markup can be written as normal, but with variable substitution to insert dynamic values.

#!/bin/bash

MEMINFO=$(cat /proc/meminfo|grep Mem)
CPUINFO=$(cat /proc/cpuinfo |egrep 'vendor|MHz|model name|cache size')

echo -ne "20 text/gemini\r\n"

cat <<EOGEMINI
# Server Info

## Mem info
${MEMINFO}

## CPU info
${CPUINFO}

### Generated by: ${0}
EOGEMINI

The link below runs a similar bash script, and also shows the environment variables that are set by the server before launching the process.

Here's where the script lives and its permissions.

kevin@server:~/gemini/content/cgi-bin$ ls -l serverinfo
-rwxr-xr-x 1 kevin kevin 716 Jul 13 19:57 serverinfo

A view of TLS variables from CGI scripts

The following output was taken from an AV-98 session where I set up a client certificate. Note that when I select a certificate (that I had previously generated using option 2) the prompt changes to 'AV-98+cert'.

You can see that, when the request is made with a client certificate, the CGI variable TLS_CLIENT_HASH is set to the fingerprint of the certificate. This value is the same as is returned by the 'openssl x509' command below. The man page of this command describes the fingerprint as 'the digest of the DER encoded version of the entire certificate'.

kevin@gemini:~$ openssl x509 -noout -fingerprint -sha256 -in ./my_very_own_certificate.crt

SHA256 Fingerprint=88:B8:AE:F5:2C:0B:06:AB:04:70:07:7D:E4:84:B4:03:94:C7:28:9D:74:81:44:84:8F:77:20:FC:E0:72:C0:62

The AV-98 example below shows me selecting a client certificate prior to making a request to my CGI script.

AV-98> cert
Managing client certificates
1. Deactivate client certificate.
2. Generate new certificate.
3. Load previously generated certificate.
4. Load externally created client certificate from file.
Enter blank line to exit certificate manager.
> 3
1. kevin
> 1
AV-98+cert> go gemini://gemini.susa.net/cgi-bin/serverinfo

Here is the output generated by a request with the client certificate enabled, note that TLS_CLIENT_HASH contains a value that's unique to my certificate.

Server Info

Mem info
MemTotal:        2003296 kB
MemFree:          444716 kB
MemAvailable:    1154528 kB

CPU info
vendor_id       : GenuineIntel
model name      : Intel Xeon Processor (Skylake, IBRS)
cpu MHz         : 2099.998
cache size      : 16384 KB

CGI Vars
• GEMINI_URL: gemini://gemini.susa.net/cgi-bin/serverinfo
• SERVER_NAME: gemini.susa.net
• SERVER_PROTOCOL: GEMINI
• SERVER_SOFTWARE: gemserv
• SCRIPT_NAME: /cgi-bin/serverinfo
• REMOTE_ADDR: ::ffff:78.46.186.193
• REMOTE_HOST: ::ffff:78.46.186.193
• REMOTE_PORT: 54448
• QUERY_STRING:
• PATH_INFO:

• AUTH_TYPE: Certificate
• TLS_CLIENT_HASH: SHA256:88B8AEF52C0B06AB0470077DE484B40394C7289D748144848F7720FCE072C062
• REMOTE_USER: Kevin

Generated by: /home/kevin/gemini/content/cgi-bin/serverinfo

The output below was generated by a request where no client certificate was enabled for the request, note that TSL_CLIENT_HASH is empty.

Server Info

Mem info
MemTotal:        2003296 kB
MemFree:          420916 kB
MemAvailable:    1131736 kB

CPU info
vendor_id       : GenuineIntel
model name      : Intel Xeon Processor (Skylake, IBRS)
cpu MHz         : 2099.998
cache size      : 16384 KB

CGI Vars
• GEMINI_URL: gemini://gemini.susa.net/cgi-bin/serverinfo
• SERVER_NAME: gemini.susa.net
• SERVER_PROTOCOL: GEMINI
• SERVER_SOFTWARE: gemserv
• SCRIPT_NAME: /cgi-bin/serverinfo
• REMOTE_ADDR: ::ffff:78.46.186.193
• REMOTE_HOST: ::ffff:78.46.186.193
• REMOTE_PORT: 54456
• QUERY_STRING:
• PATH_INFO:

• AUTH_TYPE:
• TLS_CLIENT_HASH:
• REMOTE_USER:

Generated by: /home/kevin/gemini/content/cgi-bin/serverinfo