Hello, My server is implemented in PHP and I would like add client certificate support, but I cannot seem to find the right option for this. I tried setting capture_peer_cert to true in the context options, but it does not seem to work, and the documentation is, well, sporadic. You can read my code on gemini://code.lanterne.chilliet.eu/vendor/mcmic/gemini-server/src/Server.php Are there any Gemini server in PHP with client cert support? C?me
I ran into the same problem when trying to add client certificate support on my PHP server (https://tildegit.org/sumpygump/orbit) I think that `capture_peer_cert` is intended to only work with stream_socket_client and not with socket servers. I started looking at the source code of PHP to see if I could find the part that handles the TLS handshake to find out if there is any way to get access to the cert that came along with the connection, but I have not been successful in my search yet. On Sun, Dec 13, 2020 at 11:12 AM C?me Chilliet <come at chilliet.eu> wrote: > Hello, > > My server is implemented in PHP and I would like add client certificate > support, but I cannot seem to find the right option for this. > > I tried setting capture_peer_cert to true in the context options, but it > does not seem to work, and the documentation is, well, sporadic. > > You can read my code on gemini:// > code.lanterne.chilliet.eu/vendor/mcmic/gemini-server/src/Server.php > > Are there any Gemini server in PHP with client cert support? > > C?me > > > -- Jansen Price 612-886-5065 jansen.price at gmail.com
Le dimanche 13 d?cembre 2020, 18:28:38 CET Jansen Price a ?crit : > I ran into the same problem when trying to add client certificate support > on my PHP server (https://tildegit.org/sumpygump/orbit) > > I think that `capture_peer_cert` is intended to only work > with stream_socket_client and not with socket servers. I started looking at > the source code of PHP to see if I could find the part that handles the TLS > handshake to find out if there is any way to get access to the cert that > came along with the connection, but I have not been successful in my search > yet. I tried posting on php-internals ML, but no answer so far: https://news-web.php.net/php.internals/112495 We can try the bug tracker but I?ve seen bugs related to streams and/or encryption with no answer since a long time :-/ I think the best solution is to try to come with a PR. C?me
twins provides client certificate hashes via $_SERVER. https://gitlab.com/tslocum/twins/blob/master/CONFIGURATION.md#fastcgi
Le dimanche 13 d?cembre 2020, 18:28:38 CET Jansen Price a ?crit : > I ran into the same problem when trying to add client certificate support > on my PHP server (https://tildegit.org/sumpygump/orbit) > > I think that `capture_peer_cert` is intended to only work > with stream_socket_client and not with socket servers. I started looking at > the source code of PHP to see if I could find the part that handles the TLS > handshake to find out if there is any way to get access to the cert that > came along with the connection, but I have not been successful in my search > yet. So, I found something, it does work if you set verify_peer to true in the ssl context options. The problem is that if you do so, a request without a client certificate will fail, even before you can know what is the request. I?m not sure if you can change the context once a connection is accepted, if yes maybe you can attempt stream_socket_enable_crypto once with verify_peer and if it fails run it again without it, but it feels non-optimized. This is related to the openssl behavior of https://www.openssl.org/docs/man1.1.1/man3/SSL_get_peer_certificate.html It says: "Due to the protocol definition, a TLS/SSL server will always send a certificate, if present. A client will only send a certificate when explicitly requested to do so by the server (see SSL_CTX_set_verify(3))." According to https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_verify.html , a client certificate request is sent by the server only if SSL_VERIFY_PEER is set, which php will only set if verify_peer is true. However, even if I was implementing this in C it is not clear to me how to request a client certificate without making it mandatory, is that what SSL_VERIFY_CLIENT_ONCE is for? Are there Gemini servers in C with client certificate support of which I could read the code out there? C?me
It was thus said that the Great C?me Chilliet once stated: > > However, even if I was implementing this in C it is not clear to me how to > request a client certificate without making it mandatory, is that what > SSL_VERIFY_CLIENT_ONCE is for? Are there Gemini servers in C with client > certificate support of which I could read the code out there? You might want to check out the source code to LibreSSL (a fork of OpenSSL). It comes with a TLS wrapper in the form of libtls (in the tls/ directory), which has the function tlsconf_verify_client_optional(). You might be able to follow the logic of that function (vs. tlsconf_verify_client()) to see how it works. -spc
C?me Chilliet <come at chilliet.eu> writes: > [snip] > However, even if I was implementing this in C it is not clear to me how to request a client certificate without making it mandatory, is that what SSL_VERIFY_CLIENT_ONCE is for? > Are there Gemini servers in C with client certificate support of which I could read the code out there? > > C?me I've written my server[0] using LibreSSL (a fork of OpenSSL) and it supports client certs. The code is quite short (a bit more than 1k lines) but the key points for your question are these two lines[1]: /* optionally accept client certs, but don't try to verify them */ tls_config_verify_client_optional(conf); tls_config_insecure_noverifycert(conf); you need to enable optionally the client certs and the tell the library to not verify the certs. I don't know how to help you in PHP, but I hope this can help a bit :) [0]: https://github.com/omar-polo/gmid [1]: https://github.com/omar-polo/gmid/blob/master/gmid.c#L1076-L1078
Omar Polo <op at omarpolo.com> writes: > C?me Chilliet <come at chilliet.eu> writes: >> [snip] >> However, even if I was implementing this in C it is not clear to me how to request a client certificate without making it mandatory, is that what SSL_VERIFY_CLIENT_ONCE is for? >> Are there Gemini servers in C with client certificate support of which I could read the code out there? >> >> C?me > > I've written my server[0] using LibreSSL (a fork of OpenSSL) and it > supports client certs. The code is quite short (a bit more than 1k > lines) but the key points for your question are these two lines[1]: > > /* optionally accept client certs, but don't try to verify them */ > tls_config_verify_client_optional(conf); > tls_config_insecure_noverifycert(conf); > > you need to enable optionally the client certs and the tell the library > to not verify the certs. > > I don't know how to help you in PHP, but I hope this can help a bit :) > > [0]: https://github.com/omar-polo/gmid > [1]: https://github.com/omar-polo/gmid/blob/master/gmid.c#L1076-L1078 I forgot to address a point > I?m not sure if you can change the context once a connection is accepted, if yes maybe you can attempt stream_socket_enable_crypto once with verify_peer and if it fails run it again without it, but it feels non-optimized. I don't think you can do this. Once a connection is established, the certificates have already been checked, so you need to act before. and I also forgot to mention that I'm not using directly the libressl api, but I'm using instead libtls (a wrapper with nicer APIs)
2020/12/21 10:42, C?me Chilliet: > Current PHP cannot do that. Not sure what would be the best API for > this feature if it was added. Most likely a new context option for ssl > which says the client cert is optional. I guess to be complete it > would allow disabling client cert validation all together, or only > when client cert is absent. > > An other solution is to allow PHP code to set its own callback, but it > seems to be dangerous and hard to use. I feel your pain, client certs seem to be not very widely used so a lot for platforms don't support them out of the box. For d??m?ni, I have/had a similar problem with racket, its standard ssl implementation does not handle client certificates at all, so I ended up breaking it open and allowing SSL_CTX_set_verify to be set with SSL_VERIFY_PEER. Access to the actual client certificate from the connection context turned out a lot harder in openssl racket setup, so, yes, I went with dangerous and hard (passing certificate info through a thread local). I already had fiddle with thread locals to do SNI (another thing apparently not very popular in racket) so I kinda got used to that.. For details see: https://git.sr.ht/~rwv/dezhemini/tree/client-cert/item/openssl-extra.rkt and search for verify-callback in: https://git.sr.ht/~rwv/dezhemini/tree/client-cert/item/dezhmnsrv.rkt Cheers, R.
---
Previous Thread: How do You publish to your gemlog?
Next Thread: [ANN] SmolNetSharp - C# library for building Gemini/Gopher clients