Coder Social home page Coder Social logo

stgloorious / acme-client Goto Github PK

View Code? Open in Web Editor NEW
0.0 2.0 0.0 430 KB

Simple ACME client written in C

License: GNU General Public License v3.0

CMake 4.56% C 83.71% Shell 11.50% Python 0.24%
acme acme-client certificates letsencrypt pki tls

acme-client's Introduction

acme-client

Build Test codecov

Simple ACME client written in C

What is ACME?

ACME (Automatic Certificate Management Environment) is a protocol specified by RFC 8555 that is widely used for obtaining Let's Encrypt and other certificates automatically. A user (ACME client machine, usually automated) can request a certificate for a domain it has control over by sending a request to an ACME server. The ACME server will then generate challenges for the client which have to be fulfilled in order to prove control over the requested domains. A challenge is a random token that the client needs to serve via HTTP or DNS TXT record. If the conditions are met and the challenges are fulfilled before timeout, the server will issue the certificate and make it available for the client.

Features

  • Single or multidomain certificate requests to an ACME-enabled CA, such as Let's Encrypt
  • HTTP-01 validation
  • Automatic HTTP challenge validation, no user interaction required

Usage

Usage: acme-client [OPTION...]
Simple ACME client written in C

  -a, --account-key=KEYFILE  Account private key
  -c, --cert=CERTFILE        CA certificate file used by the ACME server
  -d, --domain=DOMAIN        Domain for which to request the certificate. Can
                             be used multiple times.
  -p, --port=PORT            Port number the HTTP server should bind to
  -u, --dir=DIR_URL          Directory URL of the ACME server that should be
                             used.
  -v, --verbose              Produce verbose output
  -y, --agree-tos            Always agree to the terms of service
  -?, --help                 Give this help list
      --usage                Give a short usage message
  -V, --version              Print program version

Examples

Obtaining a Let's Encrypt certificate

  1. Stop your webserver, so acme-client can bind to Port 80. For instance if you're using nginx and systemd:

     systemctl stop nginx
    
  2. Run acme-client

     ./acme-client --domain <YOUR-DOMAIN-NAME>
    
  3. Copy client.key and cert.crt to the right location & restart webserver

     systemctl start nginx
    

Installation

A binary release is planned as soon as acme-client is more stable. For now, you have to compile it yourself. Linux only.

acme-client comes in two configurations: Debug and Release. The debug build contains all the tests that are also used in the Github testing CI pipeline. It has some unit tests and does testing against a local ACME testing server. It uses Valgrind to spot memory leaks and other memory-related issues.

Building from source

Dependencies

Besides a standard GCC installation you need the following packages. For the release build:

  • OpenSSL >= 3.0.0
  • cURL
  • cJSON
  • CMake >= 3.20

Ubuntu 22.04 (Release build)

sudo apt-get install libcurl4-openssl-dev libcjson-dev openssl libssl-dev cmake

Needed additionally for testing (debug build):

  • Pebble
  • Python >= 3.9
  • Valgrind

Ubuntu 22.04 (Debug build)

sudo apt-get install libcurl4-openssl-dev libcjson-dev openssl libssl-dev cmake valgrind pebble

Using CMake

Get the sources:

git clone https://github.com/stgloorious/acme-client && cd acme-client

Compile (Release build):

cmake -DCMAKE_BUILD_TYPE=Release -B build
cd build && make

Compile and test (Debug build):

cmake -DCMAKE_BUILD_TYPE=Debug -B build
cd build && make all test

acme-client's People

Contributors

stgloorious avatar

Watchers

Arisu avatar  avatar

acme-client's Issues

Root certificate url is hardcoded

https://pebble:15000/roots/0 is hardcoded and will be added to the certificate chain so a different pebble hostname and/or port will not work. With other servers than pebble, it may also fail.

Support for dns01 validation

Currently, domain verification is only possible using HTTP (http01 challenge). Support for verification via DNS TXT records (dns-01) would allow for more flexibility.

Segfault if there is an error while receiving the certificate

Error parsing certificate chain: did not receive PEM certificate:
{
 "type": "urn:ietf:params:acme:error:badNonce",
 "detail": "JWS has an invalid anti-replay nonce: -YTNXyJfgzSX5lq0K92Lvg",
 "status": 400
}
Pebble 2022/12/29 18:39:26 POST /certZ/ -> calling handler()
bash: line 1: 14467 Segmentation fault      (core dumped)

Support for wildcard domains

Currently it is not possible to request a certificate for a wildcard domain (like *.example.com). For wildcard domains, dns01 must be supported. See #7 .

Account key is hardcoded

Currently there is no support for different client keys that are used to identify the account holder. This is not as terrible as it may sound like, because the domain validation through e.g. http-01 is still necessary and private keys for the actual certificate are separate and are generated for every certificate.

Valgrind error

Fails testing pipeline

==16354== 
==16354== HEAP SUMMARY:
==16354==     in use at exit: 18,612 bytes in 317 blocks
==16354==   total heap usage: 95,696 allocs, 95,379 frees, 17,097,038 bytes allocated
==16354== 
==16354== 3 bytes in 1 blocks are indirectly lost in loss record 1 of 159
==16354==    at 0x484DCD3: realloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==16354==    by 0x4A1C617: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x4A130BC: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x4A323FA: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x4AFAC17: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x4AFBB17: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x49C7F80: OSSL_DECODER_do_all_provided (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x49D535B: OSSL_DECODER_CTX_new_for_pkey (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x4A3FB16: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x4A3FEB1: PEM_read_bio_PrivateKey_ex (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==16354==    by 0x111CB4: crypt_read_key (crypt.c:97)
==16354==    by 0x111F1E: crypt_new_key (crypt.c:125)
==16354== 
==16354== 

Segfault if bind to port 80 is not possible

./acme-client --dir https://pebble:14000/dir --domain example.com --cert=../test/pebble/pebble.minica.pem
segfaults after the message "Error: HTTP challenge server bind failed."

This does not occur if --port is correctly set to the port on which pebble is listening (5080 in this case)

HTTPS testing server has problems with certificate

Certificate is ready.
Certificate saved to cert.crt
Killed Pebble server PID 14348
/usr/bin/python3
Started HTTPS server on port 5443 with PID 14394
/home/runner/work/acme-client/acme-client/test/https_server.py:9: DeprecationWarning: ssl.wrap_socket() is deprecated, use SSLContext.wrap_socket()
  httpd.socket = ssl.wrap_socket(httpd.socket, certfile=sys.argv[1], server_side=True)
Traceback (most recent call last):
  File "/home/runner/work/acme-client/acme-client/test/https_server.py", line 9, in <module>
    httpd.socket = ssl.wrap_socket(httpd.socket, certfile=sys.argv[1], server_side=True)
  File "/usr/lib/python3.10/ssl.py", line 1439, in wrap_socket
    context.load_cert_chain(certfile, keyfile)
ssl.SSLError: [SSL] PEM lib (_ssl.c:3874)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to foobar.domain.com port 5443 after 0 ms: Connection refused

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.