- insecure-fork-wanted
- insecure-setuid-wanted
- issuers-chain-path
+ - jwt.decrypt_alg_list
+ - jwt.decrypt_enc_list
- key-base
- limited-quic
- localpeer
The OCSP features are able to use the completed chain when no .issuer was
used, or no chain was provided in the PEM.
+jwt.decrypt_alg_list <list>
+ Set the list of algorithms allowed in the jwt_decrypt_XXX converters. JWT
+ tokens using an unsupported or disabled algorithms will never be decrypted.
+ The specified algorithms must have the same format as in section 4.1 of
+ RFC7518 and must be colon-separated. The special "ALL" name can be used to
+ enable all the supported algorithms (see "jwt_decrypt_jwk" converter for a
+ complete list) and a '!' can be appended to an algorithm name to explicitly
+ disable it.
+ Please note that unless "ALL" is specified, using this option will disable
+ any algorithm that is not explicitly mentioned in the provided list.
+
+ Examples:
+ # Enable all algorithms but the "ECDH-ES" one
+ jwt.decrypt_alg_list ALL:!ECDH-ES
+
+ # Only enable ECDH-ES algorithms
+ jwt.decrypt_alg_list ECDH-ES:ECDH-ES+A128KW:ECDH-ES+A192KW:ECDH-ES+A256KW
+
+jwt.decrypt_enc_list <list>
+ Set the list of encryption algorithms allowed in the jwt_decrypt_XXX
+ converters. JWT tokens using an unsupported or disabled encryption algorithms
+ will never be decrypted.
+ The specified algorithms must have the same format as in section 5.1 of
+ RFC7518 and must be colon-separated. The special "ALL" name can be used to
+ enable all the supported algorithms (see "jwt_decrypt_jwk" converter for a
+ complete list) and a '!' can be appended to an algorithm name to explicitly
+ disable it.
+ Please note that unless "ALL" is specified, using this option will disable
+ any algorithm that is not explicitly mentioned in the provided list.
+
+ Examples:
+ # Enable only AES GCM encrypting algorithms
+ jwt.decrypt_enc_list A128GCM:A192GCM:A256GCM
+
key-base <dir>
Assigns a default directory to fetch SSL private keys from when a relative
path is used with "key" directives. Absolute locations specified prevail and
the JOSE header) among the following: RSA1_5, RSA-OAEP, RSA-OAEP-256,
ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW or ECDH-ES+A256KW.
+ The supported algorithms and encryption algorithms ("alg" and "enc" fields of
+ the JOSE header respectively) can be modified thanks to the
+ 'jwt.decrypt_alg_list' and 'jwt.decrypt_enc_list' global options.
+
The JWE token must be provided base64url-encoded and the output will be
provided "raw". If an error happens during token parsing, signature
verification or content decryption, an empty string will be returned.
so the A128KW, A192KW, ECDH-ES+A128KW and ECDH-ES+A192KW algorithms won't
work.
+ The supported algorithms and encryption algorithms ("alg" and "enc" fields of
+ the JOSE header respectively) can be modified thanks to the
+ 'jwt.decrypt_alg_list' and 'jwt.decrypt_enc_list' global options.
+
The JWE token must be provided base64url-encoded and the output will be
provided "raw". If an error happens during token parsing, signature
verification or content decryption, an empty string will be returned.
struct alg_enc {
const char *name;
int value;
+ int enabled;
};
/* https://datatracker.ietf.org/doc/html/rfc7518#section-4.1 */
// JWE_ALG_PBES2_HS512_A256KW,
} jwe_alg;
-struct alg_enc jwe_algs[] = {
- { "RSA1_5", JWE_ALG_RSA1_5 },
- { "RSA-OAEP", JWE_ALG_RSA_OAEP },
- { "RSA-OAEP-256", JWE_ALG_RSA_OAEP_256 },
- { "A128KW", JWE_ALG_A128KW },
- { "A192KW", JWE_ALG_A192KW },
- { "A256KW", JWE_ALG_A256KW },
- { "dir", JWE_ALG_DIR },
- { "ECDH-ES", JWE_ALG_ECDH_ES },
- { "ECDH-ES+A128KW", JWE_ALG_ECDH_ES_A128KW },
- { "ECDH-ES+A192KW", JWE_ALG_ECDH_ES_A192KW },
- { "ECDH-ES+A256KW", JWE_ALG_ECDH_ES_A256KW },
- { "A128GCMKW", JWE_ALG_A128GCMKW },
- { "A192GCMKW", JWE_ALG_A192GCMKW },
- { "A256GCMKW", JWE_ALG_A256GCMKW },
- { "PBES2-HS256+A128KW", JWE_ALG_UNMANAGED },
- { "PBES2-HS384+A192KW", JWE_ALG_UNMANAGED },
- { "PBES2-HS512+A256KW", JWE_ALG_UNMANAGED },
- { NULL, JWE_ALG_UNMANAGED },
+enum {
+ ALG_ENC_DISABLED = 0,
+ ALG_ENC_ENABLED = 1
+};
+
+struct alg_enc jwe_algs_dflt[] = {
+ { "RSA1_5", JWE_ALG_RSA1_5, ALG_ENC_ENABLED },
+ { "RSA-OAEP", JWE_ALG_RSA_OAEP, ALG_ENC_ENABLED },
+ { "RSA-OAEP-256", JWE_ALG_RSA_OAEP_256, ALG_ENC_ENABLED },
+ { "A128KW", JWE_ALG_A128KW, ALG_ENC_ENABLED },
+ { "A192KW", JWE_ALG_A192KW, ALG_ENC_ENABLED },
+ { "A256KW", JWE_ALG_A256KW, ALG_ENC_ENABLED },
+ { "dir", JWE_ALG_DIR, ALG_ENC_ENABLED },
+ { "ECDH-ES", JWE_ALG_ECDH_ES, ALG_ENC_ENABLED },
+ { "ECDH-ES+A128KW", JWE_ALG_ECDH_ES_A128KW, ALG_ENC_ENABLED },
+ { "ECDH-ES+A192KW", JWE_ALG_ECDH_ES_A192KW, ALG_ENC_ENABLED },
+ { "ECDH-ES+A256KW", JWE_ALG_ECDH_ES_A256KW, ALG_ENC_ENABLED },
+ { "A128GCMKW", JWE_ALG_A128GCMKW, ALG_ENC_ENABLED },
+ { "A192GCMKW", JWE_ALG_A192GCMKW, ALG_ENC_ENABLED },
+ { "A256GCMKW", JWE_ALG_A256GCMKW, ALG_ENC_ENABLED },
+ { "PBES2-HS256+A128KW", JWE_ALG_UNMANAGED, ALG_ENC_DISABLED },
+ { "PBES2-HS384+A192KW", JWE_ALG_UNMANAGED, ALG_ENC_DISABLED },
+ { "PBES2-HS512+A256KW", JWE_ALG_UNMANAGED, ALG_ENC_DISABLED },
+ { NULL, JWE_ALG_UNMANAGED, ALG_ENC_DISABLED },
};
+struct alg_enc *jwe_algs = NULL;
+
/* https://datatracker.ietf.org/doc/html/rfc7518#section-5.1 */
typedef enum {
JWE_ENC_UNMANAGED = -1,
JWE_ENC_A256GCM,
} jwe_enc;
-struct alg_enc jwe_encodings[] = {
- { "A128CBC-HS256", JWE_ENC_A128CBC_HS256 },
- { "A192CBC-HS384", JWE_ENC_A192CBC_HS384 },
- { "A256CBC-HS512", JWE_ENC_A256CBC_HS512 },
- { "A128GCM", JWE_ENC_A128GCM },
- { "A192GCM", JWE_ENC_A192GCM },
- { "A256GCM", JWE_ENC_A256GCM },
- { NULL, JWE_ENC_UNMANAGED },
+struct alg_enc jwe_encodings_dflt[] = {
+ { "A128CBC-HS256", JWE_ENC_A128CBC_HS256, ALG_ENC_ENABLED },
+ { "A192CBC-HS384", JWE_ENC_A192CBC_HS384, ALG_ENC_ENABLED },
+ { "A256CBC-HS512", JWE_ENC_A256CBC_HS512, ALG_ENC_ENABLED },
+ { "A128GCM", JWE_ENC_A128GCM, ALG_ENC_ENABLED },
+ { "A192GCM", JWE_ENC_A192GCM, ALG_ENC_ENABLED },
+ { "A256GCM", JWE_ENC_A256GCM, ALG_ENC_ENABLED },
+ { NULL, JWE_ENC_UNMANAGED, ALG_ENC_DISABLED },
};
+struct alg_enc *jwe_encodings = NULL;
+
/*
* In the JWE Compact Serialization, a JWE is represented as the concatenation:
while (item->name) {
if (strncmp(item->name, b_orig(buf), (int)b_data(buf)) == 0) {
+ if (item->enabled == ALG_ENC_DISABLED)
+ return -1;
val = item->value;
break;
}
}
+/*
+ * Duplicate algorithm and encoding arrays so that their enabled flags
+ * can be overwritten (when using the jwt.encrypt_alg/enc_list options).
+ * Return 0 in case of success, -1 otherwise.
+ */
+static int dup_alg_enc_arrays(void)
+{
+ int ret = -1;
+
+ if (!jwe_algs) {
+ jwe_algs = malloc(sizeof(jwe_algs_dflt));
+ if (!jwe_algs) {
+ ha_alert("Unable to allocate the JWE algorithms array.\n");
+ goto end;
+ }
+ memcpy(jwe_algs, jwe_algs_dflt, sizeof(jwe_algs_dflt));
+ }
+
+ if (!jwe_encodings) {
+ jwe_encodings = malloc(sizeof(jwe_encodings_dflt));
+ if (!jwe_encodings) {
+ ha_alert("Unable to allocate the JWE encodings array.\n");
+ goto end;
+ }
+ memcpy(jwe_encodings, jwe_encodings_dflt, sizeof(jwe_encodings_dflt));
+ }
+
+ ret = 0;
+
+end:
+ return ret;
+}
+
+static int jwe_init(void)
+{
+ /* Duplicate algorithm and encoding arrays so that their enabled flags
+ * can be overwritten */
+ return dup_alg_enc_arrays();
+}
+
+REGISTER_PRE_CHECK(jwe_init);
+
+static void jwe_deinit(void)
+{
+ ha_free(&jwe_algs);
+ ha_free(&jwe_encodings);
+}
+
+REGISTER_POST_DEINIT(jwe_deinit);
+
+/*
+ * Look for an entry named <algname> in array <arr> and set its 'enabled' field
+ * to <value>.
+ * Return 0 in case of success, 1 otherwise (item not found).
+ */
+static int set_alg_enc_flag(struct alg_enc *arr, char *algname, int algname_len, int value)
+{
+ struct alg_enc *item = &arr[0];
+
+ while (item->name) {
+ if (algname_len == strlen(item->name) && strncmp(algname, item->name, algname_len) == 0) {
+ item->enabled = value;
+ return 0;
+ }
+ ++item;
+ }
+
+ return 1;
+}
+
+/* Set the 'enabled' field to <val> for all members of <arr>. */
+static void set_all_alg_enc_flags(struct alg_enc *arr, int val)
+{
+ struct alg_enc *item = &arr[0];
+
+ while (item->name) {
+ item->enabled = val;
+ ++item;
+ }
+}
+
+/*
+ * Parse algorithm list comprised of colon-separated algorithms having the same
+ * format as in jwe_algs_dflt or jwe_encodings_dflt arrays.
+ * When the option is used, all the algorithms are first disabled so any
+ * unspecified algo will not be enabled anymore.
+ */
+static int jwe_parse_global_alg_enc_list(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ struct alg_enc *arr = NULL;
+ char *p, *arg = args[1];
+ char *arg_end = arg+strlen(arg);
+ char *alg, *alg_end;
+
+ int value = ALG_ENC_ENABLED;
+ int ret = -1;
+
+ if (dup_alg_enc_arrays())
+ goto end;
+
+ if (args[0][14] == 'a') {
+ /* "jwe.supported_algorithms" */
+ arr = jwe_algs;
+ } else {
+ /* "jwe.supported_encodings" */
+ arr = jwe_encodings;
+ }
+
+ /* Disable all algorithms/encodings */
+ set_all_alg_enc_flags(arr, ALG_ENC_DISABLED);
+
+ while (*arg) {
+ value = ALG_ENC_ENABLED;
+
+ if (*arg == '!') {
+ ++arg;
+ value = ALG_ENC_DISABLED;
+ }
+ alg = arg;
+ alg_end = NULL;
+
+ p = strchr(arg, ':');
+ if (p) {
+ alg_end = p;
+ arg = p + 1;
+ } else {
+ alg_end = arg_end;
+ arg = arg_end;
+ }
+
+ /* If "ALL" is used all previously disabled algo will be
+ * reenabled */
+ if (strncmp(alg, "ALL", alg_end - alg) == 0) {
+ set_all_alg_enc_flags(arr, ALG_ENC_ENABLED);
+ } else {
+ if (set_alg_enc_flag(arr, alg, alg_end-alg, value) != 0) {
+ memprintf(err, "Unknown algorithm/encoding %.*s\n", (int)(alg_end-alg), alg);
+ goto end;
+ }
+ }
+ }
+
+ ret = 0;
+end:
+ return ret;
+
+}
+
+static struct cfg_kw_list cfg_kws = {ILH, {
+ { CFG_GLOBAL, "jwt.decrypt_alg_list", jwe_parse_global_alg_enc_list },
+ { CFG_GLOBAL, "jwt.decrypt_enc_list", jwe_parse_global_alg_enc_list },
+ { 0, NULL, NULL },
+}};
+
+INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
+
+
static struct sample_conv_kw_list sample_conv_kws = {ILH, {
/* JSON Web Token converters */
{ "jwt_decrypt_secret", sample_conv_jwt_decrypt_secret, ARG1(1,STR), sample_conv_jwt_decrypt_secret_check, SMP_T_BIN, SMP_T_BIN },