From: William Lallemand Date: Wed, 2 Apr 2025 16:52:24 +0000 (+0200) Subject: MINOR: acme: add private key configuration X-Git-Tag: v3.2-dev11~100 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf6a39c4d1b37d6ec1b3846408ce930d82aaab37;p=thirdparty%2Fhaproxy.git MINOR: acme: add private key configuration This commit allows to configure the generated private keys, you can configure the keytype (RSA/ECDSA), the number of bits or the curves. Example: acme LE uri https://acme-staging-v02.api.letsencrypt.org/directory account account.key contact foobar@example.com challenge HTTP-01 keytype ECDSA curves P-384 --- diff --git a/include/haproxy/acme-t.h b/include/haproxy/acme-t.h index 127660e7a..685bef0da 100644 --- a/include/haproxy/acme-t.h +++ b/include/haproxy/acme-t.h @@ -16,6 +16,12 @@ struct acme_cfg { EVP_PKEY *pkey; /* account PKEY */ char *thumbprint; /* account PKEY JWS thumbprint */ } account; + + struct { + int type; /* EVP_PKEY_EC or EVP_PKEY_RSA */ + int bits; /* bits for RSA */ + int curves; /* NID of curves */ + } key; char *challenge; /* HTTP-01, DNS-01, etc */ struct acme_cfg *next; }; diff --git a/src/acme.c b/src/acme.c index 9c97b4138..156caea75 100644 --- a/src/acme.c +++ b/src/acme.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static struct acme_cfg *acme_cfgs = NULL; @@ -59,6 +60,13 @@ struct acme_cfg *new_acme_cfg(const char *name) ret->challenge = strdup("HTTP-01"); /* default value */ + /* The default generated keys are EC-384 */ + ret->key.type = EVP_PKEY_EC; + ret->key.curves = NID_secp384r1; + + /* default to 4096 bits when using RSA */ + ret->key.bits = 4096; + ret->next = acme_cfgs; acme_cfgs = ret; @@ -267,6 +275,71 @@ out: return err_code; } +static int cfg_parse_acme_cfg_key(char **args, int section_type, struct proxy *curpx, const struct proxy *defpx, + const char *file, int linenum, char **err) +{ + int err_code = 0; + char *errmsg = NULL; + + if (strcmp(args[0], "keytype") == 0) { + if (!*args[1]) { + ha_alert("parsing [%s:%d]: keyword '%s' in '%s' section requires an argument\n", file, linenum, args[0], cursection); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + if (alertif_too_many_args(1, file, linenum, args, &err_code)) + goto out; + + if (strcmp(args[1], "RSA") == 0) { + cur_acme->key.type = EVP_PKEY_RSA; + } else if (strcmp(args[1], "ECDSA") == 0) { + cur_acme->key.type = EVP_PKEY_EC; + } else { + ha_alert("parsing [%s:%d]: keyword '%s' in '%s' section requires either 'RSA' or 'ECDSA' argument\n", file, linenum, args[0], cursection); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + } else if (strcmp(args[0], "bits") == 0) { + char *stop; + + if (!*args[1]) { + ha_alert("parsing [%s:%d]: keyword '%s' in '%s' section requires an argument\n", file, linenum, args[0], cursection); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + cur_acme->key.bits = strtol(args[1], &stop, 10); + if (*stop != '\0') { + err_code |= ERR_ALERT | ERR_FATAL; + ha_alert("parsing [%s:%d] : cannot parse '%s' value '%s', an integer is expected.\n", file, linenum, args[0], args[1]); + goto out; + } + + if (alertif_too_many_args(1, file, linenum, args, &err_code)) + goto out; + + } else if (strcmp(args[0], "curves") == 0) { + if (!*args[1]) { + ha_alert("parsing [%s:%d]: keyword '%s' in '%s' section requires an argument\n", file, linenum, args[0], cursection); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + if (alertif_too_many_args(1, file, linenum, args, &err_code)) + goto out; + + if ((cur_acme->key.curves = curves2nid(args[1])) == -1) { + ha_alert("parsing [%s:%d]: unsupported curves '%s'\n", file, linenum, args[1]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + } + +out: + free(errmsg); + return err_code; +} + /* Initialize stuff once the section is parsed */ static int cfg_postsection_acme() { @@ -388,6 +461,9 @@ static struct cfg_kw_list cfg_kws_acme = {ILH, { { CFG_ACME, "contact", cfg_parse_acme_kws }, { CFG_ACME, "account", cfg_parse_acme_kws }, { CFG_ACME, "challenge", cfg_parse_acme_kws }, + { CFG_ACME, "keytype", cfg_parse_acme_cfg_key }, + { CFG_ACME, "bits", cfg_parse_acme_cfg_key }, + { CFG_ACME, "curves", cfg_parse_acme_cfg_key }, { 0, NULL, NULL }, }};