GithubHelp home page GithubHelp logo

omar-polo / gmid Goto Github PK

View Code? Open in Web Editor NEW
101.0 5.0 8.0 2.67 MB

a Gemini server

Home Page: https://gmid.omarpolo.com

License: ISC License

Makefile 2.11% Roff 4.29% C 81.31% Shell 3.29% Dockerfile 0.07% Yacc 4.36% HTML 0.04% Perl 1.30% CSS 1.53% Vim Script 1.70%
gemini gemini-protocol libtls gemini-server

gmid's Introduction

gmid

gmid is a full-featured Gemini server written with security in mind. It can serve static files, has optional FastCGI and proxying support, and a rich configuration syntax.

A few helper programs are shipped as part of gmid:

  • gg is a simple command-line Gemini client.

  • gemexp is a stripped-down config-less version of gmid to quickly serve a directory from the command line.

  • titan is a command-line titan client.

Internationalisation (IRIs, UNICODE, punycode, all that stuff)

Even thought the current Gemini specification doesn't mention anything in this regard, I do think these are important things and so I tried to implement them in the most user-friendly way I could think of.

For starters, gmid has full support for IRI (RFC3987 — Internationalized Resource Identifiers). IRIs are a superset of URIs, so there aren't incompatibilities with URI-only clients.

There is full support also for punycode. In theory, the user doesn't even need to know that punycode is a thing. The hostname in the configuration file can (and must be) in the decoded form (e.g. naïve and not xn--nave-6pa), gmid will do the rest.

The only missing piece is UNICODE normalisation of the IRI path: gmid doesn't do that (yet).

Configuration

gmid has a rich configuration file, heavily inspired by OpenBSD' httpd(8), with every detail carefully documented in the manpage. Here's a minimal example of a config file:

# /etc/gmid.conf
server "example.com" {
	listen on * port 1965
	cert "/path/to/cert.pem"
	key  "/path/to/key.pem"
	root "/var/gemini/example.com"
}

and a slightly more complex one

# /etc/gmid.conf
cert_root = "/path/to/keys"

server "example.com" {
	listen on * port 1965

	alias "foobar.com"

	cert $cert_root "/example.com.crt"
	key  $cert_root "/example.com.pem"
	root "/var/gemini/example.com"

	# lang for text/gemini files
	lang "en"

	# only for locations that matches /files/*
	location "/files/*" {
		# generate directory listings
		auto index on
	}

	location "/repo/*" {
		# change the index file name
		index "README.gmi"
		lang "it"
	}
}

Building

gmid depends on libevent2, LibreSSL or OpenSSL, and yacc or GNU bison.

The build is as simple as

$ ./configure
$ make

If the configure scripts fails to pick up something, please open an issue or notify me via email.

To install execute:

# make install

Please keep in mind that the master branch, from time to time, may be accidentally broken on some platforms. gmid is developed primarily on OpenBSD/amd64 and commits on the master branch don't get always tested in other OSes. Before tagging a release however, a comprehensive testing on various platform is done to ensure that everything is working as intended.

Testing

Execute

$ make regress

to start the suite. Keep in mind that the regression tests needs to create a few file inside the regress directory and bind the 10965 port.

Contributing

Any form of contribution is welcome, not only patches or bug reports. If you have a sample configuration for some specific use-case, a script or anything that could be useful to others, consider adding it to the contrib directory.

Architecture/Security considerations

The internal architecture was revisited for the 2.0 release. For earlier releases, please refer to previous revision of this file.

gmid has a privsep design, where the operations done by the daemon are splitted into multiple processes:

  • main: the main process is the only one that keeps the original privileges. It opens the TLS certificates on the behalf of the server and crypto processes, reloads the configuration upon SIGHUP and re-opens the log files upon SIGUSR1.

  • logger: handles the logging with syslog and/or local files.

  • server: listens for connections and serves the request. It also speaks FastCGI and do the proxying.

  • crypto: holds the TLS private keys to avoid a compromised server process to disclose them.

gmid's People

Contributors

cybertailor avatar eniehack avatar klapacz avatar la-ninpre avatar nytpu avatar omar-polo avatar sir-photch avatar the-king-of-toasters avatar toby222 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

gmid's Issues

tls error: handshake failed: Success

Feb 19 20:24:20 aiko gmid: 2607:fea8:4f1f:4c00:4439:56fd:d875:199b:48516 GET  59 Wrong/malformed host or missing SNI
Feb 19 20:24:20 aiko gmid: 2607:fea8:4f1f:4c00:4439:56fd:d875:199b:48516 tls error: handshake failed: Success
Feb 19 20:24:20 aiko gmid: 2607:fea8:4f1f:4c00:4439:56fd:d875:199b:48516 unknown bufferevent error: Success

I'm not sure if this is actually an issue -- for one, I have no idea what's on the other end of this log message, and whether the connection even could succeed -- but I can't help but share this error message and wonder if you could perhaps enlighten me how can a handshake fail successfully. :)

I'm seeing it on average once a day.

speak the proxy protocol when proxying

This is the mirror of #28, not for accepting requests but rather for when gmid proxies. Should support at least v1, so we can add some regress test for the proxy protocol handling.

debugging sandbox issue on arm64

Hello there,

I'm trying to get gmid to work with sandbox enabled on a raspberry pi 4 with gentoo linux. I uncommented the #define SC_DEBUG line as you tell in the faq, but I don't see any "unexpected syscall" line even if all tests are failing. What could it be?

Without sandboxing it works fine.

test output:

make 'TESTS=' -C regress all
make[1]: Entering directory '/home/user/gmid/regress'
./regress 
OK:  foo => foo
OK:  h.n => h.n
OK:  xn-invalid => xn-invalid
OK:  naïve => naïve
OK:  xn--8ca => è
OK:  xn--caff-8oa => caffè
OK:  xn--nave-6pa => naïve
OK:  xn--e-0mbbc => τeστ
OK:  xn--8ca67lbac => τèστ
OK:  xn--28j2a3ar1p => こんにちは
OK:  xn--hello--ur7iy09x => hello-世界
OK:  xn--hi--hi-rr7iy09x => hi-世界-hi
OK:  xn--caf-8la.foo.org => cafè.foo.org
OK:  xn--j6h => ♨
OK:  xn--x73l => 𩸽
OK:  xn--x73laaa => 𩸽𩸽𩸽𩸽
test_punycode passed
=> http://omarpolo.com
=> omarpolo.com
=> gemini:/omarpolo.com
=> gemini//omarpolo.com
=> h!!p://omarpolo.com
=> GEMINI://omarpolo.com
=> gemini://omarpolo.com
=> gemini://omarpolo.com/
=> gemini://omarpolo.com:1965
=> gemini://omarpolo.com:1965/
=> gemini://omarpolo.com:196s
=> gemini://OmArPoLo.CoM
=> gemini://xn--nave-6pa.omarpolo.com
=> gemini://naïve.omarpolo.com
=> gemini://na%c3%afve.omarpolo.com
=> gemini://omarpolo.com/foo/bar/baz
=> gemini://omarpolo.com/foo//bar///baz
=> gemini://omarpolo.com/foo/./bar/./././baz
=> gemini://omarpolo.com/foo/bar/../bar/baz
=> gemini://omarpolo.com/foo/../foo/bar/../bar/baz/../baz
=> gemini://omarpolo.com/foo/..
=> gemini://omarpolo.com/foo/../
=> gemini://omarpolo.com/foo/../..
=> gemini://omarpolo.com/foo/../../
=> gemini://omarpolo.com/foo/../foo/../././/bar/baz/.././.././/
=> gemini://omarpolo.com//foo
=> gemini://omarpolo.com/////foo
=> http://a/b/c/../..
=> gemini://example.com/@f:b!(z$&)/baz
=> foo://example.com/foo/?gne
=> foo://example.com/foo/?gne&foo
=> foo://ex.com/robots.txt?name=foobar&url=https://foo.com
=> foo://ex.com/[email protected]#quuz
=> foo://bar.co/#foo
=> foo://bar.com/caf%C3%A8.gmi
=> foo://bar.com/caff%C3%A8%20macchiato.gmi
=> foo://bar.com/caff%C3%A8+macchiato.gmi
=> foo://bar.com/foo%2F..%2F..
=> foo://bar.com/foo%00?baz
=> foo://bar.com/cafè.gmi
=> foo://bar.com/世界.gmi
=> foo://bar.com/😼.gmi
=> foo://bar.com/😼/𤭢.gmi
=> foo://bar.com/世界/��
test_iri passed
gg: connect: can't connect to localhost:10965: Connection refused
gg: connect: can't connect to localhost:10965: Connection refused
./tests.sh: line 19: kill: (11503) - No such process
Header mismatch
wants : 20 text/gemini
got   : 
test_configless_mode failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_static_files failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 30 /dir/
got   : 
test_directory_redirect failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 application/octet-stream
got   : 
test_serve_big_files failed
gg: timer expired
Header mismatch
wants : 20 application/octet-stream
got   : 
test_dont_execute_scripts failed
gg: timer expired
Header mismatch
wants : 20 text/x-funny
got   : 
test_custom_mime failed
gg: timer expired
Header mismatch
wants : 20 application/x-foo
got   : 
test_default_type failed
gg: timer expired
Header mismatch
wants : 20 text/gemini;lang=it
got   : 
test_custom_lang failed
test_parse_custom_lang_per_location passed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_cgi_scripts failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 application/octet-stream
got   : 
test_cgi_big_replies failed
gg: timer expired
Unexpected number of args
want : 1
got  : 0
test_cgi_split_query failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_custom_index failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/plain
got   : 
test_custom_index_default_type_per_location failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_auto_index failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 40 temporary failure
got   : 
test_block failed
gg: timer expired
Header mismatch
wants : 40 % /foo.gmi  10965 localhost test
got   : 
test_block_return_fmt failed
gg: timer expired
Header mismatch
wants : 20 text/plain; lang=en
got   : 
test_entrypoint failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 60 client certificate required
got   : 
test_require_client_ca failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 51 not found
got   : 
test_root_inside_location failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 31 /foo/
got   : 
test_root_inside_location_with_redirect failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_fastcgi failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_macro_expansion failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 51 not found
got   : 
test_174_bugfix failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_proxy_relay_to failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_proxy_with_certs failed
gg: timer expired
gg: timer expired
Header mismatch
wants : 59 Wrong/malformed host or missing SNI
got   : 
test_unknown_host failed
gg: timer expired
Header mismatch
wants : 20 text/gemini
got   : 
test_include_mime failed

failed tests: test_configless_mode test_static_files test_directory_redirect test_serve_big_files test_dont_execute_scripts test_custom_mime test_default_type test_custom_lang test_cgi_scripts test_cgi_big_replies test_cgi_split_query test_custom_index test_custom_index_default_type_per_location test_auto_index test_block test_block_return_fmt test_entrypoint test_require_client_ca test_root_inside_location test_root_inside_location_with_redirect test_fastcgi test_macro_expansion test_174_bugfix test_proxy_relay_to test_proxy_with_certs test_unknown_host test_include_mime
make[1]: *** [Makefile:12: all] Error 1
make[1]: Leaving directory '/home/user/gmid/regress'
make: *** [Makefile:165: regress] Error 2

Multi-domain reverse proxy

Hello,

I want to use single IPv4 to make proxy for 2 domains, but on defining 2 servers as on example - get certificate mismatch

server "betahowto.duckdns.org" {
	listen on 94.140.114.89 port 1965
	cert "/home/gmid/betahowto.duckdns.org/cert.pem"
	key "/home/gmid/betahowto.duckdns.org/key.rsa"

	proxy {
		relay-to 301:5eb5:f061:678e::b port 1965
		verifyname off
	}
}

server "kevachat.duckdns.org" {
	listen on 94.140.114.89 port 1965
	cert "/home/gmid/kevachat.duckdns.org/cert.pem"
	key "/home/gmid/kevachat.duckdns.org/key.rsa"

	proxy {
		relay-to 201:23b4:991a:634d:8359:4521:5576:15b7 port 1965
		verifyname off
	}
}

Support for raw TCP reverse proxies that talk ProxyProtocol

Hi, I was wondering if you'd have any interest in gmid being able to talk tcp proxy protocol?
This would alleviate the need for another instance of gmid acting as the reverse proxy in front of the "actual" gmid server.

To be specific, I already have a nginx reverse proxy that also handles other ports / hosts, and right now, I can configure nginx to proxy_pass TCP streams via the nginx_stream_proxy_module on port 1965 to some other host. This works nicely.

However, now my proxy IP is shown in the logs of gmid, instead of the actual remote host. (Granted, I can log the access at the nginx-site, but that won't give me any info about the actual path that was requested.)

This could be fixed by gmid accepting the proxy protocol, which is designed to preserve the requesting host IP while passing through proxies.

Anyway, thanks for this software. It is very BSD-esque :)

server "IPv6"?

I'm using Yggdrasil, and want to host capsule without regular domain name.

By defining in config IPv6, e.g. server "[xxx:xxxx:xxxx:xxxx:xx]" - get incomplete header error.

With /etc/hosts it works using domain alias but with IP not

How is it supposed to be used (not installed)

I didn't quite understand from the README or the website how to actually run the server. How does it run? What's the default config file name? I read the man page but I wonder if it could be run (or if it's supposed to be) from inetd or a service with rcctl (I'm using OpenBSD). I had no luck with vger either (which does require inetd and a proxy).

Get "fatal in gmid: chroot path too long: /var/gemini/chroot

After a package update from 2.0.4 to 2.0.5 on FreeBSD 14.1-RELEASE-p0 I get the following error:

$ gmid -f
fatal in gmid: chroot path too long: /var/gemini/chroot
fatal in gmid: chroot path too long: /var/gemini/chroot
fatal in gmid: chroot path too long: /var/gemini/chroot
one child died, quitting
lost child: pid 79626 exited abnormally
lost child: pid 79495 exited abnormally
lost child: pid 79275 exited abnormally
fatal in gmid: chroot path too long: /var/gemini/chroot
lost child: pid 79712 exited abnormally
fatal in gmid: chroot path too long: /var/gemini/chroot
lost child: pid 79958 exited abnormally
parent terminating, pid 78990

Had to downgrade to 2.0.4 to work properly again. Can't help much with figuring out the error because it runs only on my production machine.

cgi with chroot always 42

Every time I make a request to a cgi file to my gmid server, I get a 42 CGI error.
After some debugging, it seems that this execvp call always fails with No such file or directory, despite the file definitely existing and being executable by the gmid user.
Console output showing File Not Found error
image

The regression tests work fine, so I think it might be an error with chroot being configured
I've been trying to debug this with low-to-mediocre C-skill but ran out of ideas.


I'm running gmid on my RasPi with Arch arm for armv7 architecture.
(I needed to SC_ALLOW fstatat64, _llseek, and sigreturn to stop errors there)

I'm using this config:

port 1965
user "gmid"

chroot "/var/gemini"

server "home.tobot.dev" {
  cert "/etc/ssl/certs/home.tobot.dev.cert.pem"
  key "/etc/ssl/private/home.tobot.dev.privkey.pem"

  root "/home.tobot.dev"
  auto index on

  cgi "*"
}

server "localhost" {
  cert "/etc/ssl/certs/localhost.pem"
  key "/etc/ssl/private/localhost.key"

  root "/home.tobot.dev"
  auto index on

  cgi "*"
}

log files are not opened inside the chroot

Got gmid going today on my FBSD server with the chroot configuation. Wanted to use a text logfile. At first I created the path within the chroot but server couldn't open it. Realized it may be an exception to chroot, created in the main filesystem and it worked.

The documentation for the chroot option currently reads "All the paths in the configuration file are relative to the chroot directory, except for the cert, key and ocsp paths." Also the log access option says "The path is relative to the chroot."

My experience is that this is misleading, and a change to the documentation may be warranted. Alternatively, if the plan is to open the logfile within the chroot, this is not my experience.

gmid 2.0

I've mentioned before in some issue and in private conversations but never said clearly (outside of commit messages): the next release of gmid will be 2.0 and have some breaking changes.

The master branch is currently the work-in-progress for the future 2.0 so use it at your own risk. The documentation is incomplete. For something stable and documented, please use the latest 1.8.X release (currently 1.8.4) that will keep to receive updates until 2.0 is out. Said that, if you want to help squashing out bugs you're encouraged to try the master.

My plan is to try fix all of the things that would require a breaking change in 2.0 to provide a stable interface again after.

The biggest change is an internal one, half of which is already been done: fixing privsep. We had an "executor" process that was some sort of hack to do all the nice things we can't do in a sandbox. The server process asked this "executor" to run CGI scripts, open network sockets for proxying and/or fastcgi. I wanted to get rid of this because it's a way to escape the sandbox, and this has been done. Now it's the server process that opens the network sockets and CGI script support has been removed (see d29a2ee, the alternative is to use FastCGI with for e.g. slowcgi-portable). The downside is that we loose the sandbox for the server process outside of OpenBSD.

The other half of the privsep issue is to make the internal process handling better. The configuration should be sent over imsg and the sub-processes spawned only once at startup. Imsg handling should be fully asynchronous.

Running as uid 0 and chroot should also probably be made mandatory, or at least enabled by default.

Another invasive, but less than the previous, change to do is to allow binding to specific ip/ports per vhost, and possibly multiple times. Each server block should have a listen on directive and the global port one should be removed.

The fastcgi support should be extended to allow setting and changing parameters more easily, and under the hood it would be nice to "batch" multiple fastcgi params instead of one-per-record. FastCGI multiplexing is really nice but probably won't be done in time for 2.0.

If there are other things that would require a breaking change, feel free to open an issue so they can be discussed before 2.0. There isn't a clearly defined deadline for it, but I'd like to get it done by the end of the year.

As always, patches are welcome! :)

Support for other protocols (gopher, spartan, ...)

In the past I've discarded the feature requests to add support for other protocols, since I saw gmid only as a gemini server. The idea was that if there was the need for a gmid-style server for spartan or gopher, a new server could be written (eventually borrowing from gmid.)

However this doesn't seem much viable practically speaking, and with also #19 there is some room to discuss adding other protocols to gmid. I'm fearing in part that we'd become a kitchen sink, but there is also some value in speaking a few adjacent protocols: the code won't explode in size and the service is nice.

This feature has to be planned carefully however. The protocol(s) implementation may be trivial, but the configuration changes have to be planned.

For example, gopher doesn't have (AFAIK) the notion of virtual hosts, so the server block makes little sense. On the other hand, stuff like the TLS settings makes sense only for gemini. On the third (?) hand, some options will need to be handled per-protocol (index comes to mind).

Titan (see #19) could also be "plugged" this way.

One way to handle this could be by introducing a protocol block. I still fear that we'd have to treat each protocol as it were a tiny snowflake in the configuration syntax anyway. We shouldn't be limited by the backward compatibility: at least initially let's try to design something that makes sense; we'll deal with the backward compat only when we have a nice design.

The milestone is temporary 2.2 (don't want to delay 2.1) but it could also be 3.0. Titan may be moved from 2.1 to this milestone.

Thoughts?

GG: /.. reported as invalid IRI

Requesting the address gemini://localhost/../ returns the error gg: invalid IRI: illegal path, even though it should be a valid IRI
gemini://localhost/./...../ (arbitrarily many . at the end) works, and will return the index of localhost, if requested on a gmid server

Cross-compilation support

I've tried to cross-compile gmid on x86 for rasberryPi (armv6l) and configure script failed with:

...
gmid-armv6l-unknown-linux-gnueabihf> tested noop-static: no (compilation failed)
gmid-armv6l-unknown-linux-gnueabihf> selected STATIC=""
gmid-armv6l-unknown-linux-gnueabihf> tested err: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested explicit_bzero: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested freezero: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested getdtablecount: no (compilation failed)
gmid-armv6l-unknown-linux-gnueabihf> tested getdtablesize: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested getprogname: no (compilation failed)
gmid-armv6l-unknown-linux-gnueabihf> tested imsg-lutil: no (compilation failed)
gmid-armv6l-unknown-linux-gnueabihf> tested libevent: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested libtls: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested openssl: no (execution fa
iled)
gmid-armv6l-unknown-linux-gnueabihf> tested pr_set_name: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested program_invocation_short_name: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested program_invocation_short_name-D_GNU_SOURCE: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested queue_h: no (compilation failed)
gmid-armv6l-unknown-linux-gnueabihf> tested reallocarray: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested recallocarray: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested setproctitle: no (compilation failed)
gmid-armv6l-unknown-linux-gnueabihf> tested strlcat: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested strlcpy: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested strtonum: no (compilation failed)
gmid-armv6l-unknown-linux-gnueabihf> tested vasprintf: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> tested vasprintf-D_GNU_SOURCE: no (execution failed)
gmid-armv6l-unknown-linux-gnueabihf> FATAL: libtls not found
...

libtls not found since HAVE_LIBTLS=0:

gmid/configure

Lines 257 to 261 in e4116fb

if [ ${HAVE_LIBTLS} -eq 0 ]; then
echo "FATAL: libtls not found" 1>&2
echo "FATAL: libtls not found" 1>&3
exit 1
fi

HAVE_LIBTLS=0 since test binary cannot be executed on build host:

gmid/configure

Lines 179 to 196 in e4116fb

if ./have/${1} 1>&3 2>&3; then
echo "tested ${n}: yes" 1>&2
echo "result of running ${n}: yes" 1>&3
echo 1>&3
eval HAVE_${2}=1
[ "${3}" = "-D_GNU_SOURCE" ] && NEED_GNU_SOURCE=1
[ "${3}" = "-D_OPENBSD_SOURCE" ] && NEED_OPENBSD_SOURCE=1
[ "${3}" = "-lutil" ] && LD_IMSG="-lutil"
rm "have/${1}"
return 0
else
echo "tested ${n}: no (execution failed)" 1>&2
echo "result of ${n}: execution failed with exit status $?" 1>&3
echo "result of running ${n}: no" 1>&3
echo 1>&3
rm "have/${1}"
return 1
fi

Reverse proxy support

Hi!

My gemini server does not support TLS shutdown and this feature will probably be mandatory in the future, so I am considering to change for an other gemini server. The only thing I need is support for virtual hosts, statics files and reverse proxy.
Gmid seems to be a great choice but I'm not sure for the support of reverse proxy, is it supported or planned ?
If this is not planned could it be easily added ?

Crash when logging request from handle_handshake

I was testing out gmid by connecting with openssl s_client, and noticed that if SNI is missing, it crashes when trying to log the request because c->iri has not been populated yet:

==837== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==837==  Access not within mapped region at address 0x0
==837==    at 0x4A75870: strlcpy (in /usr/lib/libbsd.so.0.10.0)
==837==    by 0x10AC16: log_request (gmid.c:123)
==837==    by 0x10DDBD: start_reply (server.c:274)
==837==    by 0x10D958: handle_handshake (server.c:200)
==837==    by 0x10EBB9: handle (server.c:577)
==837==    by 0x10EF7B: loop (server.c:665)
==837==    by 0x10B574: listener_main (gmid.c:332)
==837==    by 0x10B975: main (gmid.c:459)

Titan support?

While personally I don't like the titan protocol, it seems it's starting to gain popularity in the Geminispace.

I don't want gmid to start modifying files, so one way to handle titan would be via FastCGI and/or proxying. In both situation it would be a separate program to handle the titan request, and gmid would only need to do some basic validation but otherwise forward the request as-is.

Systematic CGI error when in daemon mode

Hello, this issue may be related to #15

System information

OS: FreeBSD 13.2-RELEASE-p2 GENERIC
Version: gmid 1.8.6

/usr/local/etc/gmid.conf

user "_gmid"
chroot "/var/gemini"

server "gmiusr.timeopochin.xyz" {
        root "/gmiusr/public"
        cgi  "/*"

        cert "/usr/local/etc/ssl/gmid/gmiusr.timeopochin.xyz.cert.pem"
        key  "/usr/local/etc/ssl/gmid/gmiusr.timeopochin.xyz.key.pem"
}

Behaviour

Any request to a CGI script leads to 42 CGI error

Expected behaviour

Request to working CGI scripts should not return an error

Observations

Any request to a *.gmi file works as expected.
This is only a problem when running gmid with the -c flag:

gmid -d /usr/local/etc/ssl/gmid -x '/*' -H gmiusr.timeopochin.xyz /var/gemini/gmiusr/public

works as expected.

gmid sometimes throws CGI error

gmid sometimes throws CGI error

stderr logs:

x.x.x.x:56284 GET gemini://hyperstorm.hu/linkek.gmi 20 text/gemini
x.x.x.x:56286 GET gemini://hyperstorm.hu/index.gmi 20 text/gemini; charset=utf-8
x.x.x.x:56288 GET gemini://hyperstorm.hu/linkek.gmi 20 text/gemini
x.x.x.x:56290 GET gemini://hyperstorm.hu/index.gmi 20 text/gemini; charset=utf-8
x.x.x.x:56292 GET gemini://hyperstorm.hu/gemini-halozat.gmi 20 text/gemini
x.x.x.x:56294 GET gemini://hyperstorm.hu/gemini-halozat.gmi 20 text/gemini
x.x.x.x:56296 GET gemini://hyperstorm.hu/linkek.gmi 20 text/gemini
y.y.y.y:35335 GET gemini://hyperstorm.hu/index.gmi 42 CGI error
y.y.y.y:35598 GET gemini://hyperstorm.hu/index.gmi 42 CGI error
y.y.y.y:34932 GET gemini://hyperstorm.hu/index.gmi 42 CGI error
x.x.x.x:56298 GET gemini://hyperstorm.hu/index.gmi 42 CGI error
x.x.x.x:56300 GET gemini://hyperstorm.hu/index.gmi 42 CGI error
x.x.x.x:56304 GET gemini://hyperstorm.hu/index.gmi 42 CGI error
root@Hyperstorm:~# gmid.linux.amd64 -f -vv -c /etc/gmid.conf --> here I restarted the server
x.x.x.x:56306 GET gemini://hyperstorm.hu/index.gmi 20 text/gemini; charset=utf-8
x.x.x.x:56308 GET gemini://hyperstorm.hu/index.gmi 20 text/gemini; charset=utf-8
x.x.x.x:56310 GET gemini://hyperstorm.hu/index.gmi 20 text/gemini; charset=utf-8
x.x.x.x:56312 GET gemini://hyperstorm.hu/index.gmi 20 text/gemini; charset=utf-8

System:
Linux Hyperstorm 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u2 (2019-11-11) x86_64 GNU/Linux
Distributor ID: Debian
Description: Debian GNU/Linux 10 (buster)
Release: 10
Codename: buster

Log location.

Might be a dumb question, but I cannot find anywhere else.

Does gmid keeps a log of what happens and the requests it serves? Like what gemexp outputs to stdout
Where is the default location for that?
I can't find it.

Thanks in advance.

gmid 1.8 compile in tinycore

Hello @omar-polo,

im trying out tinycore linux on an eeepc900 and im planning to use a local gemini server to keep tracks of my stuff and hopefully i'll be in the space soonish! gmid is not (yet 😛 ) packaged for tinycore so i tryed to compile it. Here's my experience it might be useful to others as well, some things might be useful to you as well.

First thing, dependencies, im sorry to bring this up again, the bad naming around libtls/libretls drove me crazy and it took me sometime to grasp my head around. If you are running tinycore you might want to look for openssl+libretls (aka libtls for openssl). libtls should be compiled as well.

If you want to get your life easier consider using the metapackage compiletc, you need to install as well the other dependencies (libevent-dev, openssl-dev, compiletc should take care of the rest).

The quickstart guide is where you want to look next and it's clear and straight to the point to set you up. If you need help with certificates gmid comes with a handy helper too (check the contrib folder).

I tried to start up gmid 1.8 (latest release) in foreground and verbose mode, but i have no luck in getting it working, i had no idea where to look for output or errors. The following is the dead simple config i've tried:

server "localhost" {
	cert "/tmp/test/localhost.pem"
	key  "/tmp/test/localhost.key"

	# path to the root directory of your capsule
	root "/tmp/test"
}

I then repeat the same step again but with the latest code and it worked, gmid in foreground was giving me helpful info, i had to change the "server" directive to server "localhost.local" to get it respond properly. I might think this would let 1.8 work as well i'll try later today.

PS: i understand that this suit best on the tinycore forum, first i would like to address the 1.8 issue, it's probably me and should be some configuration issue or the essential tinycore spirit and a few things must have be done to make it work properly.

PSPS: i'd love to read about your workflow to keep, write and maintain you gemini capsule!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.