Giter VIP home page Giter VIP logo

uacme's People

Contributors

alexshpilkin avatar dengqf6 avatar ffontaine avatar halosghost avatar jacksonchen666 avatar jirutka avatar kolbma avatar ndilieto avatar sideeffect42 avatar sthen 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  avatar  avatar

Watchers

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

uacme's Issues

Allow creating private keys and directory with g+rX

I have various users on my system that need access to ssl private keys, so I use group ssl-cert for them, but uacme always sets umask such that private/* and key.pem files all end up not group readable. Would be nice if there were an option to allow group reading (setting correct group is handled because I have g+s on private/ in my case)

nsupdate.sh may fail silently with exit status to be 0

Hello,

I am adapting the sample hook script for Cloudflare API. I notice a possible problem that may cause the script to fail silently.

At the line

[ $res -eq 0 ] || break
, break is executed if ns_doupdate returns non-zero code. Then it flows to the line
return $?
, where $? is always 0 because previous res=$? (and [ $res -eq 0 ] ?) itself updates $? to be 0.

Finally, the script returns 0 even though ns_doupdate has failed.

A quick fix is to replace break with return $res.

(I do not have a bind server to test the original script. Please let me know if I missed something by mistake.)

No joy with install on Raspbian / Buster

Good morning,

I tried installing UACME on my Pi 4 (running Buster). I ran into two installation issues so far when I executed the "./configure --disable-maintainer-mode" command.

  • The first time, it failed due to a lack of libcurl. I installed that and re-ran the installation script.
  • The installer made it past libcurl but then got caught on GNUTLS missing. So I installed that too, via "sudo apt-get install gnutls-bin". The installer script still stalls and errors out, claiming that a suitable GNUTLS has not been installed.

According to the GNUTLS installer, version 3.6.7 was installed "Setting up gnutls-bin (3.6.7-4+deb10u6) ..."
Per the UACME installer, "checking for GnuTLS >= 3.3.30... no" followed by "configure: error: gnutls not found"

I must be doing something wrong so I wonder if you could make a suggestion re: GNUTLS or the version of LIBCURL that should be installed as a pre-requisite to installing UACME. I would also like to make the suggestion to reference these and any other packages that must be installed before UACME to make the process easier for newbies like me. Thank you for writing UACME!

Constantin

Return code from --version should probably be 0

uacme --version 2> /dev/null && echo "OK" || echo "Nope"

This is a common way to determine whether or not the program is present. However, uacme returns a failure code, non-zero, from this command and from uacme --help.

1.7.5 cross compile failure

with the new update, cross compile doesn't work anymore:

checking for sys/un.h... yes
checking for mmap... yes
checking if mmap(MAP_ANON|MAP_SHARED) works... configure: error: in `/home/build/proxy/build_dir/target-x86_64_musl/uacme-upstream-1.7.5':
configure: error: cannot run test program while cross compiling
See `config.log' for more details

configure:7108: checking for mmap
configure:7108: x86_64-openwrt-linux-musl-gcc -o conftest -Os -pipe -g3 -fno-caller-saves -fno-plt -fhonour-copts -fmacro-prefix-map
=/home/build/proxy/build_dir/target-x86_64_musl/uacme-upstream-1.7.5=uacme-upstream-1.7.5 -Wformat -Werror=format-security -fstack-p
rotector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro  -I/home/build/proxy/staging_dir/toolchain-x86_64_gcc-12.3.0_musl/usr/include -
I/home/build/proxy/staging_dir/toolchain-x86_64_gcc-12.3.0_musl/include -I/home/build/proxy/staging_dir/toolchain-x86_64_gcc-12.3.0_
musl/include/fortify  -I/home/build/proxy/staging_dir/target-x86_64_musl/usr/include -L/home/build/proxy/staging_dir/toolchain-x86_6
4_gcc-12.3.0_musl/usr/lib -L/home/build/proxy/staging_dir/toolchain-x86_64_gcc-12.3.0_musl/lib -fuse-ld=bfd -znow -zrelro -Wl,--gc-s
ections,--as-needed  -L/home/build/proxy/staging_dir/target-x86_64_musl/usr/lib conftest.c -lssl -lcrypto  >&5
configure:7108: $? = 0
configure:7108: result: yes
configure:7119: checking if mmap(MAP_ANON|MAP_SHARED) works
configure:7122: error: in `/home/build/proxy/build_dir/target-x86_64_musl/uacme-upstream-1.7.5':
configure:7124: error: cannot run test program while cross compiling
See `config.log' for more details

run hooks parallel

I would like to have the hooks run parallel. Our DNS provider is quite slow and a change needs up to 20. min. This adds up pro domain.

You haven't considered that having multiple hooks run in parallel will result in very problematic race conditions, for example multiple hooks changing the same webserver or DNS configuration at once.

Actually I have considered this and noticed the scripts currently can run in parallel. Because multiple certs can contain the same domain.

Hooks would need to implement their own locking mechanism to avoid this.

For http and dns challenges this is not a problem, because it's save to assume that the token/auth is different for each challenge.

For tls-alpn ualpn.c might needs some locking, but I would say it's required anyway.

Could not find pkg-config

If I am trying to install like described on the main page, I'll get an error after running ./configure --disable-maintainer-mode.

[...]
checking sys/socket.h usability... yes
checking sys/socket.h presence... yes
checking for sys/socket.h... yes
checking for sys/stat.h... (cached) yes
checking for sys/types.h... (cached) yes
checking sys/wait.h usability... yes
checking sys/wait.h presence... yes
checking for sys/wait.h... yes
checking for asprintf... yes
checking for vasprintf... yes
checking for getopt_long... yes
checking for setproctitle... no
checking for pkg-config... no
configure: error: Could not find pkg-config

Unpredictable behavior between `issue IDENTIFIER` and `issue CSRFILE`

I ran into an issue recently where running this command:

doas -u acme uacme -v www.domain.com

resulted in the somewhat cryptic message:

uacme: failed to stat www.domain.com: Permission denied

This was a result of running uacme as an unprivileged user while in a directory to which it has no read-access (ie /root), which then causes this call to fail, since uacme doesn't know whether the single argument is for a CSR file or a domain name.

Would it be possible to check if the stat error is due to permission denied instead of just a missing file, or alternatively add an additional command-line flag to force uacme to treat the input as a domain name instead of a file? I think it would at least be good to have a better error message, since I assumed it was due to uacme not having access to one of the directories it needed for writing the certificates.

add option to define custom certificate subdirectory (?)

Hi,

would you consider support for an option by which the default "IDENTIFIER" part in determining the storage location for the certificate to be issued can be replaced by a custom, arbitrary value?

While it does probably make not too much sense to have multiple certificates with the same first identifier/common name, it is not strictly invalid and would not work well/at all with the default paths.

I'm in a situation where the actual certificate configuration is outside of my control and I would like to not have to restrict the choice of certificate (subject alternatives) names and at the same time avoid any potential collisions, which I currently do by using a different unique identifier.

PR using "-u" for this: #34

Compilation failed on ArchLinux.

CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /home/build.dir/uacme/src/uacme/build-aux/missing aclocal-1.14 
/home/build.dir/uacme/src/uacme/build-aux/missing: line 81: aclocal-1.14: command not found

Missing aclocal-1.14, but installed aclocal-1.16

Error recognition fails if parameter is present in reply's "Content-Type" header

Hi,

fooling around with uacme and pebble I noticed that account creation always fails. I found that pebble returns the header Content-Type: application/probjem+json; charset=utf-8 in its error replies, which is perfectly valid according to https://tools.ietf.org/html/rfc7231#section-3.1.1.1

Due to using strcasecmp for comparision, this fails on several places, including account creation, which is then wrongly aborted.

I guess the most simple fix would be to just use strncasecmp on those 4 occasions.

RFC 8738 support / externalAccountBinding problem with ZeroSSL API?

Hi, this is probably two issues in one ;) I need to automate certificate installation for a large network of decentralized clients with static IP addresses but no domain. I came across RFC 8738, I believe uacme is one of the first ACME clients to support this new standard? Let's Encrypt doesn't support it yet (it's in pebble but not boulder), which CA did you test against?

For now I'm trying to use it with ZeroSSL, which supports ACME and IP certificates, but I'm getting the following authentication error (probably unrelated to RFC 8738):

uacme: version 1.5 starting on Sun, 29 Nov 2020 18:11:04 -0800
uacme: loading key from ./private/key.pem
uacme: fetching directory at https://acme.zerossl.com/v2/DV90
uacme: creating new account at https://acme.zerossl.com/v2/DV90/newAccount
uacme: type 'y' to accept the terms at https://secure.trust-provider.com/repository/docs/Legacy/20181101_CertificateSubscriberAgreement_v_2_1_click.html
y
uacme: failed to create account at https://acme.zerossl.com/v2/DV90/newAccount
uacme: the server reported the following error:
{
    "type": "urn:ietf:params:acme:error:externalAccountRequired",
    "status": 400,
    "detail": "The request must include a value for the \"externalAccountBinding\" field"
}

Is it possible to specify an externalAccountBinding with uacme? Thanks for thoughts on these issues!

Tests

Maybe helpful to add some automated tests of correct functionality, can make pull requests with possible tests that can be used.

uacme doesn't work with smallstep ca

Hey all,

I have a smallstep certificate authority set up for in-house ACME provisioning, and am running into issues getting uacme to work with it. When running the uacme new command, I get an error saying that the "account does not exist" (see verbose logs below). I am able to create an account and issue a cert using certbot, so I suspect this is either an issue with uacme or a combination of uacme and the smallstep setup.

I really like uacme and would love to get it working with smallstep, so let me know if there's anything else I can do to help debug. Thanks for writing a great tool!

Log:

# uacme -v -v -v -a https://<DOMAIN>/acme/acme/directory new <EMAIL>

uacme: version 1.0.21 starting on Sat, 01 Feb 2020 14:41:55 +0000
uacme: loading key from /etc/ssl/uacme/private/key.pem
uacme: fetching directory at https://<DOMAIN>/acme/acme/directory
uacme: acme_get: url=https://<DOMAIN>/acme/acme/directory
uacme: acme_get: HTTP headers
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: application/json
Replay-Nonce: <NONCE>
Date: Sat, 01 Feb 2020 14:41:55 GMT
Content-Length: 307


uacme: acme_get: HTTP body
{"newNonce":"https://<DOMAIN>/acme/acme/new-nonce","newAccount":"https://<DOMAIN>/acme/acme/new-account","newOrder":"https://<DOMAIN>/acme/acme/new-order","revokeCert":"https://<DOMAIN>/acme/acme/revoke-cert","keyChange":"https://<DOMAIN>/acme/acme/key-change"}

uacme: acme_get: return code 200, json=
{
    "newNonce": "https://<DOMAIN>/acme/acme/new-nonce",
    "newAccount": "https://<DOMAIN>/acme/acme/new-account",
    "newOrder": "https://<DOMAIN>/acme/acme/new-order",
    "revokeCert": "https://<DOMAIN>/acme/acme/revoke-cert",
    "keyChange": "https://<DOMAIN>/acme/acme/key-change"
}
uacme: fetching new nonce at https://<DOMAIN>/acme/acme/new-nonce
uacme: acme_get: url=https://<DOMAIN>/acme/acme/new-nonce
uacme: acme_get: HTTP headers
HTTP/1.1 204 No Content
Cache-Control: no-store
Replay-Nonce: <NONCE>
Date: Sat, 01 Feb 2020 14:41:55 GMT


uacme: acme_get: HTTP body

uacme: acme_get: return code 204
uacme: creating new account at https://<DOMAIN>/acme/acme/new-account
uacme: acme_post: url=https://<DOMAIN>/acme/acme/new-account payload={"onlyReturnExisting":true} protected={"alg":"RS256","nonce":"<NONCE>","url":"https://<DOMAIN>/acme/acme/new-account","jwk":{"kty":"RSA","n":"<REDACTED>","e":"<REDACTED>"}} jws={"protected":"<REDACTED>","payload":"<REDACTED>","signature":"<REDACTED>"}
uacme: acme_post: HTTP headers:
HTTP/1.1 100 Continue

HTTP/1.1 404 Not Found
Cache-Control: no-store
Content-Type: application/problem+json
Link: <https://<DOMAIN>/acme/acme/directory>;rel="index"
Replay-Nonce: <NONCE>
Date: Sat, 01 Feb 2020 14:41:55 GMT
Content-Length: 92


uacme: acme_post: HTTP body:
{"type":"urn:ietf:params:acme:error:accountDoesNotExist","detail":"Account does not exist"}

uacme: acme_post: return code 404, json=
{
    "type": "urn:ietf:params:acme:error:accountDoesNotExist",
    "detail": "Account does not exist"
}
uacme: failed to create account at https://<DOMAIN>/acme/acme/new-account
uacme: the server reported the following error:
{
    "type": "urn:ietf:params:acme:error:accountDoesNotExist",
    "detail": "Account does not exist"
}

Debian package uses libcurl3-gnutls but OpenWrt use libcurl4

I'm confusing about dependencies and would be glad if you can clarify.
On Ubuntu and Debian the uacme package depends on libcurl4.
I didn't found the debian folder with control file but apt shows these dependencies:

Depends: libc6 (>= 2.33)
  Depends: libcurl3-gnutls (>= 7.38)
  Depends: libev4 (>= 1:4.04)
  Depends: libgnutls30

So here I see that the libcurl3-gnutls is used directly by the uacme e.g. not just libcurl3 which may use a different backend by default.
Also the libgnutls30 is used directly by the uacme itself and the package was compiled with it. That's fine.

The question is why not use the libcurl4 dependency? As far I understood there is no any libcurl4-gnutls but it will internally pick up an installed backed library, right?
Update yes, it can be dynamically load an available TPS backend https://curl.se/mail/lib-2017-08/0118.html

The things become more weird for OpenWrt. There the uacme package uses the libcurl4 (not 3!) which itself depends on WolfSSL as it's now the default library for OpenWrt in last releases. But OpenWrt team working on moving back to MbedTLS.

In the same time the uacme itself depends on libmbedtls12. This is understandable but still some OpenWrt based firmwares for routers like Turris and Gl.inet are using just OpenSSL. Maybe for them it would be better to create a separate package like uacme-openssl.

Another strange thing is that the OpenWrt uacme package doesn't depend on libev. In the same time I see that the library is just included into sources. Is it statically linked or something like that?
There is some issue that may be related openwrt/packages#19015

support for --reuse-key

Hi, uacme looks very interesting to me but i could not find any information in the docs about the lifecycle of the key, I guess its renewed on renew? If so is it possible to a use or create similar option as certbot uses? ie --reuse-key.

Could not create new account on OpenWrt

Hi

This is less of an issue than a request for help because I could barely find any documentation for getting uacme to work on OpenWrt.

I successfully compiled and installed the uacme package for OpenWrt from its package source at https://github.com/openwrt/packages/tree/master/net/uacme

Then I tried to create a new account:
# uacme -v -c /etc/acme/ new
uacme: version 1.2.1 starting on Wed, 28 Oct 2020 06:28:46 -0700
uacme: created directory /etc/acme//private
uacme: loading key from /etc/acme//private/key.pem
uacme: /etc/acme//private/key.pem not found
uacme: generating new 2048-bit RSA key
uacme: key saved to /etc/acme//private/key.pem
uacme: fetching directory at https://acme-v02.api.letsencrypt.org/directory
uacme: creating new account at https://acme-v02.api.letsencrypt.org/acme/new-acct
uacme: type 'y' to accept the terms at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
y
uacme: account created at https://acme-v02.api.letsencrypt.org/acme/acct/100577813
uacme -v -c /etc/acme/ new

However, open the link https://acme-v02.api.letsencrypt.org/acme/acct/100577813, I got the following error:
{
"type": "urn:ietf:params:acme:error:malformed",
"detail": "Method not allowed",
"status": 405
}

Could I get any help here?
Thanks!
Wei

Can't compile uacme on busybox with armv7 hardware because the dependency to libcurl is not resolved correctly

Hello ndilieto,

I am trying to build uacme on my router Netgear R7800
which is running busybox on armv7l hardware.
(500 MB ram, and two cores at 1.7 ghz)

I've installed a gcc compiler , and am running the ./configure script.
the script is reporting a error that libcurl dependency cannot be resolved.

<<
checking for pkg-config... /opt/bin/pkg-config
checking pkg-config is at least version 0.28... yes
checking for libcurl >= 7.38.0... no
configure: error: libcurl not found

I have checked if the libcurl i have is meeting this requirement , and
it seems so. Opkg my package manager is listing libcurl as installed.

root@router:/opt/home/frank/uacme$ opkg list-installed | grep libcurl
libcurl - 7.68.0-1

What can i do to make uacme build?

uacme exit codes with systemd

uacme's exit codes aren't ideal for use as a systemd oneshot service:

0 Success
1 Certificate not reissued because it is still current
2 Failure (syntax or usage error; configuration error; processing failure; unexpected error).

By default systemd considers a nonzero exit code as a failure:
https://freedesktop.org/software/systemd/man/systemd.exec.html#id-1.20.4

While systemd has facilities to deal with this like SuccessExitStatus= it's far from ideal, as the status code lookup still shows 1/FAILURE. As exit 1 is the standard failure exit code for libc.

Can't call binary hook.

cat main.cr

`uacme -c /var/lib/uacme/ec -t EC -b 384 -h uacme_hook_knot issue "example.com" "*.example.com"`

cat uacme_hook_knot.cr

pp ARGV

Compile it crystal build ./main.cr
Move binary to server and try to execute

[root@webserver ~]# ./main 
uacme: uacme_hook_knot: No such file or directory

[root@webserver ~]# ls -lha /usr/bin/uacme_hook_knot 
-rwxr-xr-x 1 root root 331K Jul 31 13:43 /usr/bin/uacme_hook_knot

[root@webserver ~]# uacme_hook_knot 1 2 3 4 5
["1", "2", "3", "4", "5"]

But it works on laptop, where i compile it.
With python i got similar issue.
Upd. Now works with -h /usr/bin/uacme_hook_knot, but before it doesn't

chain and fullchain.pem

Hi,

I tried uacme and it gets cert and the key. However, it does not get chain and fullchain as done by certbot.

Can you please add feature or let me know how to do it?

Thanks

Password files

Not sure what the take or philosophy is around this, but have seen other implementations and support for encrypting keys with passwords/password-files, is it something that is within the scope of the project to enable usage of passwords/password-files?

Or perhaps there it is an intentional design-choice.

failed to find newNonce URL in directory

I'm not sure why it says this, because curling the directory shows it contains newNonce.

dcunnin@dcunnin:~$ uacme -v -c uacme.d issue fractaldemo.comy
uacme: version 1.0.18 starting on Wed, 04 Dec 2019 18:39:08 +0000
uacme: loading key from uacme.d/private/key.pem
uacme: loading key from uacme.d/private/fractaldemo.com/key.pem
uacme: checking existence and expiration of uacme.d/fractaldemo.com/cert.pem
uacme: uacme.d/fractaldemo.com/cert.pem does not exist
uacme: fetching directory at https://acme-v02.api.letsencrypt.org/directory
uacme: failed to find newNonce URL in directory
dcunnin@dcunnin:~$ curl -i https://acme-v02.api.letsencrypt.org/directory
HTTP/2 200 
server: nginx
date: Wed, 04 Dec 2019 18:39:41 GMT
content-type: application/json
content-length: 658
cache-control: public, max-age=0, no-cache
x-frame-options: DENY
strict-transport-security: max-age=604800

{
  "iiOi2bpTbTM": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
  "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
  "meta": {
    "caaIdentities": [
      "letsencrypt.org"
    ],
    "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf",
    "website": "https://letsencrypt.org"
  },
  "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct",
  "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce",
  "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order",
  "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert"
}

segfault in X509_get0_notAfter during certificate issuing

Hey @ndilieto, thanks for uacme. I like it.

I wanted to try out master, and found a segfault arising from a null pointer dereference. I bisected to 1809518 and am building it with the following configuration: ./configure --disable-maintainer-mode --with-openssl --disable-docs

(gdb) run -v issue example.com
Starting program: /usr/local/bin/uacme -v issue example.com
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
uacme: version 1.1.2 starting on Sun, 15 Mar 2020 13:00:19 +0000
uacme: loading key from /etc/ssl/uacme/private/key.pem
uacme: loading key from /etc/ssl/uacme/private/example.com/key.pem
uacme: checking existence and expiration of /etc/ssl/uacme/example.com/cert.pem
uacme: /etc/ssl/uacme/example.com/cert.pem does not exist

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7dc08a0 in X509_get0_notAfter ()
   from /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
(gdb) bt
#0  0x00007ffff7dc08a0 in X509_get0_notAfter ()
   from /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
#1  0x000055555555ff75 in cert_valid (certdir=0x55555559bf70 "/etc/ssl/uacme/example.com",
    names=0x7fffffffeb60, validity=30, status_check=true) at crypto.c:2716
#2  0x000055555555c1bb in main (argc=4, argv=0x7fffffffeb48) at uacme.c:1466
(gdb) break crypto.c:2716
Breakpoint 1 at 0x55555555ff69: file crypto.c, line 2716.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /usr/local/bin/uacme -v issue example.com
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
uacme: version 1.1.2 starting on Sun, 15 Mar 2020 13:01:24 +0000
uacme: loading key from /etc/ssl/uacme/private/key.pem
uacme: loading key from /etc/ssl/uacme/private/example.com/key.pem
uacme: checking existence and expiration of /etc/ssl/uacme/example.com/cert.pem
uacme: /etc/ssl/uacme/example.com/cert.pem does not exist

Breakpoint 1, cert_valid (certdir=0x55555559bf70 "/etc/ssl/uacme/example.com",
    names=0x7fffffffeb60, validity=30, status_check=true) at crypto.c:2716
2716        const ASN1_TIME *tm = X509_get0_notAfter(crt[0]);
(gdb) p crt[0]
$1 = (X509 *) 0x0
(gdb) p ncrt
$2 = 32767

I'm not entirely sure where 32767 is coming from, but I assume the expected behavior is for cert_load to have returned <= 0. Here's a patch for that, which fixed the issue for me:

diff --git a/crypto.c b/crypto.c
index 00488af..71acfa0 100644
--- a/crypto.c
+++ b/crypto.c
@@ -2371,6 +2371,7 @@ static int cert_load(mbedtls_x509_crt **crt, const char *format, ...)
             msg(1, "%s does not exist", certfile);
         else
             warn("cert_load: failed to open %s", certfile);
+        r = 0;
         goto out;
     }
     for (r = 0; r < (int)crt_size; r++) {

Although, you might want to double check that the patch looks good. I see that r's being reused a lot.

uacme.sh can generate invalid challenge due to echo -n

uacme.sh uses /bin/sh in the shebang which often forces shells such as bash into compatibility mode which interprets echo -n as literal output and thus creates an invalid challenge:

uacme: the server reported the following error:
{
    "type": "urn:ietf:params:acme:error:unauthorized",
    "detail": "The key authorization file from the server did not match this challenge \"tt[...]Wuo\" != \"-n tt[...]Wuo\"",
    "status": 403
}

above example was produced with

$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin20)

and the echo behavior can be checked with

$ /bin/sh -c 'echo -n'
-n

The specs say that servers SHOULD accept challenges with trailing whitespace so the easiest fix is to remove -n. A more advanced fix would be to first check that -n is safe and not use it if it's not.

Incompatibility with Mac OS X Monterrey

When I run make install I get this:

config.status: executing depfiles commands
/Library/Developer/CommandLineTools/usr/bin/make  install-am
  CC       ualpn-ualpn.o
ualpn.c:538:10: error: implicit declaration of function 'sem_timedwait' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    rc = sem_timedwait(&g_shm->sem, &ts);
         ^
ualpn.c:538:10: note: did you mean 'sem_trywait'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:58:5: note: 'sem_trywait' declared here
int sem_trywait(sem_t *);
    ^
ualpn.c:3628:13: warning: 'sem_destroy' is deprecated [-Wdeprecated-declarations]
            sem_destroy(&g_shm->logsem);
            ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:53:26: note: 'sem_destroy' has been explicitly marked deprecated here
int sem_destroy(sem_t *) __deprecated;
                         ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated    __attribute__((__deprecated__))
                                       ^
ualpn.c:3631:13: warning: 'sem_destroy' is deprecated [-Wdeprecated-declarations]
            sem_destroy(&g_shm->sem);
            ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:53:26: note: 'sem_destroy' has been explicitly marked deprecated here
int sem_destroy(sem_t *) __deprecated;
                         ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated    __attribute__((__deprecated__))
                                       ^
ualpn.c:4653:9: warning: 'sem_init' is deprecated [-Wdeprecated-declarations]
    if (sem_init(&g_shm->sem, 1, 1)) {
        ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:55:42: note: 'sem_init' has been explicitly marked deprecated here
int sem_init(sem_t *, int, unsigned int) __deprecated;
                                         ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated    __attribute__((__deprecated__))
                                       ^
ualpn.c:4658:9: warning: 'sem_init' is deprecated [-Wdeprecated-declarations]
    if (sem_init(&g_shm->logsem, 1, 1)) {
        ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:55:42: note: 'sem_init' has been explicitly marked deprecated here
int sem_init(sem_t *, int, unsigned int) __deprecated;
                                         ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated    __attribute__((__deprecated__))
                                       ^
4 warnings and 1 error generated.
make[1]: *** [ualpn-ualpn.o] Error 1
make: *** [install] Error 2

1.7.1 release tarball is missing configure script

The README instructs to start with running ./configure, but the latest release tarball does not contain one, requiring it to be generated by the user before compiling. Please update the documentation if this is intentional, or bundle a configure script in the source tarball.

Update autotools dependency

It looks like there's currently a hard dependency on aclocal-1.14. On archlinux, for example, the only version of automake available is 1.16, which leads to the following build error:

CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /home/halosghost/prj/pkg/uacme-git/src/uacme/build-aux/missing aclocal-1.14
/home/halosghost/prj/pkg/uacme-git/src/uacme/build-aux/missing: line 81: aclocal-1.14: command not found
WARNING: 'aclocal-1.14' is missing on your system.
         You should only need it if you modified 'acinclude.m4' or
         'configure.ac' or m4 files included by 'configure.ac'.
         The 'aclocal' program is part of the GNU Automake package:
         <http://www.gnu.org/software/automake>
         It also requires GNU Autoconf, GNU m4 and Perl in order to run:
         <http://www.gnu.org/software/autoconf>
         <http://www.gnu.org/software/m4/>
         <http://www.perl.org/>
make: *** [Makefile:385: aclocal.m4] Error 127

I am not hugely familiar with autotools; is this something that is easy to change so that newer versions of automake will continue to build uacme?

Set CA bundle to verify ACME Server against

I need to issue a certificate from an ACME server whose TLS certificate is not in /etc/ssl/certs/ca-certificates.crt, the default CABundle of Alpine Linux. This results in this error message:

uacme: curl_get: GET https://acme.***:8443/directory failed: SSL peer certificate or SSH remote key was not OK 

I tried setting CURL_CA_BUNDLE, but that didn't work. Is there a way to set which CA Bundle curl_get uses? For reasons I don't want to get into adding the CA to the default bundle isn't desired.

Works only on POSIX filesystems: hardlink required

I am using a filesystem which does not support hard links.
So the code like here:

uacme/uacme.c

Lines 1180 to 1186 in 7f1ffbd

if (link(certfile, bakfile) < 0) {
if (errno != ENOENT) {
warn("failed to link %s to %s", bakfile, certfile);
goto out;
}
} else
msg(1, "backed up %s as %s", certfile, bakfile);

to backup the current file fails and the cert.pem.tmp is left at its place, so I've to manually move cert.pem.tmp to cert.pem.

Similar for...

uacme/uacme.c

Lines 745 to 757 in 7f1ffbd

msg(1, "backing up %s as %s", keyfile, bakfile);
if (link(keyfile, bakfile) < 0)
warn("failed to link %s to %s", bakfile, keyfile);
else {
msg(1, "renaming %s to %s", newkeyfile, keyfile);
if (rename(newkeyfile, keyfile) < 0) {
warn("failed to rename %s to %s", newkeyfile, keyfile);
unlink(bakfile);
} else {
msg(1, "account key changed");
success = true;
}
}

Is it doable to copy the file to backup when link fails?

Like with code from here: https://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c

Potential memory allocation issue in read-file.c

You may be interested that compiling uacme with gcc v7 and
Using built-in specs. COLLECT_GCC=/opt/local/gcc7/bin/cc COLLECT_LTO_WRAPPER=/opt/local/gcc7/libexec/gcc/x86_64-sun-solaris2.11/7.4.0/lto-wrapper Target: x86_64-sun-solaris2.11
give diagnostic from realloc.
read-file.c:119:14: warning: argument 2 value '18446744073709551615' exceeds maximum object size 9223372036854775807 [-Walloc-size-larger-than=] if (!(new_buf = realloc (buf, alloc)))

How to request ocsp-must-staple on certificates

How do I pass ocsp-must-staple flag to uacme?
I grepped the source code but did not find this flag or the option.
I then looked at go-acme/lego specifically this thinking that I would create a pull request but my C language skills are failing me.
What do you suggest?

Security issue in uacme.sh

uacme/uacme.sh

Line 39 in 5afdaf0

printf "%s" "${AUTH}" > "${CHALLENGE_PATH}/${TOKEN}"

The externally controlled TOKEN variable (by the ACME server) is used to construct a path into which an externally controlled value $AUTH is written. This can be exploited by the ACME server to overwrite arbitrary files with arbitrary content.

Specify which network interface to use for ACME requests

It would be nice to have an option to specify which network interface or IP address should be used for ACME requests. When working with a large deployment which uses many certificates it can be helpful to work with several IP addresses to manage the LE rate limits.

clang reports warnings

Hello.
Just found your client, and decided that before using it, it would be interesting to see what clang --analyze would say about it.

Turns out that there are several warnings here (I will join the full log and how to generate it, since clang joins the traces it took to find the warnings):

  • null pointer passed as argument to strcasecmp/strdup
  • Potential leak of memory
  • Attempt to free released memory
  • The left operand of '==' is a garbage value
  • Access to field 'tls' results in a dereference of a null pointer

Here is how I generated that:
clang -D SYSCONFDIR='"/etc/"' -D RUNSTATEDIR='"/var/run"' -I./libev --analyze --analyzer-output text *.c > build.log 2>&1

I have also noticed warnings with a different combination of flags:

  • reports expression results being unused in the asserts. Nice trick you have, but could I suggest using assert( condition && "error message" ); instead? It does the same, but I still have to see a compiler whining about it.
  • implicit conversion changes signedness
  • macro name is a reserved identifier
  • format string is not a string literal
  • implicit conversion loses integer precision:
  • enumeration values not explicitly handled in switch (but the default keyword is used at least sometimes, so...)
  • no previous prototype for function
  • declaration shadows a local variable
  • cast from 'struct sockaddr *' to 'struct sockaddr_in *' increases required alignment (can't really be helped though)
  • padding size of 'curldata_t' with 4 bytes to alignment boundary (again, probably can't be helped, and this one only impacts memory impact AFAIK)
  • disabled expansion of recursive macro (I still have to understand the impact of this one)
  • 'HAVE_MAP_DEVZERO' is not defined, evaluates to 0 (this is my fault, since I short-circuited the makefile)
  • cast from 'const void *' to 'unsigned char *' drops const qualifier
  • cast from 'uint8_t *' (aka 'unsigned char *') to 'client_t *' (aka 'struct client *') increases required alignment from (this might be ok, but it also might trigger bugs, and that one could maybe be avoided)
  • cast from function call of type 'long' to non-matching type 'float'
  • implicit conversion increases floating-point precision:

Of course, several of those warnings have only memory performance impact or are false positives, but I believe fixing most of those would allow an easier to maintain code (shadow declarations, names reserved by the standard,...) or less prone to errors (implicit casts, for example).

Those were generated with:
clang -Wall -Weverything -D SYSCONFDIR='"/etc/"' -D RUNSTATEDIR='"/var/run"' -I./libev *.c > build2.log 2>&1
Of course, this generates linking error too, but that's unimportant considering my goal here.

You will find both the analyzer log (build.log) and the clang complains (build2.log) attached.
I intend to check if I can patch some of those quickly.

build.tar.gz

Feature request: print thumbprint of account key

I was thinking this could be useful for people that have configured their web server to statelessly respond to HTTP challenges. This has limitations but it can be done if the thumbprint of the account key is known. Any thoughts on adding a method for uacme to print the thumbprint of the current account key and then exit or similar?

nsupdate.sh: ns_getdomain selects wrong server to send updates

I just came across uacme when finally getting around to move my dns-01 setup across from some ACMEv1-only software. Thanks for writing it - I like the balance of useful features without being over-complex. It seems I picked a good time because nsupdate.sh was added recently - I ran into a few things I needed to change to get that to work for me, I'm happy to split into PRs if you like but I thought I'd discuss here first.

When trying to identify which servers should receive updates, ns_getdomain picks the last two components of the domain name (foo.bar.example.org -> example.org). This is fine for simple "domain.tld" cases with no subdomains, but fails for country TLDs like .uk where many names are registered under .co.uk/.org.uk/.net.uk, or where a zone is delegated privately.

I'm using this instead, which I think should handle all cases, at the expense of another callout to dig:

ns_getdomain()
{
    local domain=$1

    [ -n "$domain" ] || return
    set -- $($DIG +noall +authority "$domain" SOA 2>/dev/null)

    echo $1
}

A couple of other smaller things I noticed,

  • the various calls to dig using the system's default nameserver use -k RNDC_KEY, which fails at least in some situations - should those be dropped and RNDC_KEY just used for nsupdate calls?

  • there's a bashism ${res//"/} in ns_ispresent but the hashbang line is for /bin/sh (and the other scripts look like plain shell). It could be rewritten like this, or would it be preferable to change to a bash #!?

    for NS in $nameservers; do
        OLDIFS="${IFS}"
        IFS='.'
        set -- $($DIG +short "@$NS" "$fqhn" TXT 2>/dev/null)
        IFS="${OLDIFS}"
        [ "$*" = "$expect" ] || return 1
    done
  • ns_gethostname has ${ret:1} which could be replaced with ${ret#?}, but the function is unused anyway, should it just be dropped?

FYI: httpd-challenge-hook.sh

You might be interested to know that I wrote a http-01 challenge hook script that is designed for the case when you don’t need/wanna continuously run a (full-blown) web server (e.g. domain for just OpenVPN, PostgreSQL, …). Read more…

ZeroSSL keeps returning status:invalid for one out of two authorization request. Expects a retry?

Hey,

Thanks for maintaining uacme! I'm not sure who's issue this is, but I thought I'd start with uacme as you're probably more knowledgeable of the related specs than a random customer service rep from ZeroSSL.

I'm trying to to refresh a certificate with ZeroSSL that has two names --- the root and a wilcard --- example.com,*.example.com. Due to some configuration issue, the authorization was cut short yesterday. That is, only a single auth request succeeded -- for the root example.com. Since then, however, it seems ZeroSSL reuses the authorizations/challenges and considers one out of the two constantly valid and the other invalid.

In other words, the initialization returns two auths:

{
    "status": "pending",
    "expires": "2024-05-04T22:26:35Z",
    "identifiers": [
        {
            "type": "dns",
            "value": "example.com"
        },
        {
            "type": "dns",
            "value": "*.example.com"
        }
    ],
    "authorizations": [
        "https://acme.zerossl.com/v2/DV90/authz/ABC",
        "https://acme.zerossl.com/v2/DV90/authz/XYZ"
    ],
    "finalize": "https://acme.zerossl.com/v2/DV90/order/FOO/finalize"
}

The first constantly returns valid. I presume they remember that yesterday this succeeded:

{
    "identifier": {
        "type": "dns",
        "value": "example.com"
    },
    "status": "valid",
    "expires": "2024-03-05T22:26:35Z",
    "challenges": [
        {
            "type": "dns-01",
            "url": "https://acme.zerossl.com/v2/DV90/chall/XXX",
            "status": "valid",
            "validated": "2024-02-04T22:26:39Z",
            "token": "SNAFU"
        }
    ]
}

The other, the wildcard auth, constantly returns invalid:

{
    "identifier": {
        "type": "dns",
        "value": "example.com"
    },
    "status": "invalid",
    "expires": "2024-03-05T22:26:35Z",
    "challenges": [
        {
            "type": "dns-01",
            "url": "https://acme.zerossl.com/v2/DV90/chall/YYY",
            "status": "invalid",
            "error": {
            },
            "token": "SNAFU"
        }
    ],
    "wildcard": true
}

While I'm not familiar with the ACME protocol, it seems to be ZeroSSL presumes the second challenge should still be used, even though it's currently with an invalid status. Uacme, though, bails out after not seeing pending there and presumes that once the status flips to invalid, it'll never switch to valid.

So, any idea who's bug this is?

Thanks!

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.